dirmhirn
Goto Top

Outlook Ribbon xml erstellen

Hi, wir würden gerne den Report Message Button im Outlook Menü verschieben.
Datei dazu hätte ich gefunden, aber wie erstellt man die, wenn sie nicht vorhanden ist?
Das Positionieren, sobald die Datei vorhanden ist, ist kein Problem.

mso:customUI xmlns:x1=" macht Probleme. Der erste Teil ist die AppID des Report Message Tools - das wollen wir verschieben. Der zweite Teil sieht aus wie eine Mailbox ID zahlen und Großbuchstaben, ohne Trennzeichen - 32 Stellen.
O365 Mailboxen.
Die ID findet sichvzwar in der Registry, aber nirgends so, dass msn sagen könnte der User -> die ID...

Hat das schon wer geschafft?

C:\Users\%username%\AppData\Local\Microsoft\Office\olkmailread.officeUI

<mso:customUI xmlns:x1="6046742c-3aee-485e-a4ac-92ab7199db2e_XXXXXXXXXXXXXXXXX" xmlns:mso="http://schemas.microsoft.com/office/2009/07/customui">  

<mso:ribbon>

<mso:qat/>

Sg Dirm

Content-Key: 51942914712

Url: https://administrator.de/contentid/51942914712

Printed on: April 27, 2024 at 17:04 o'clock

Member: Pjordorf
Pjordorf Jan 29, 2024 at 17:18:00 (UTC)
Goto Top
Hallo,

Zitat von @Dirmhirn:
Hat das schon wer geschafft?
Frag doch mal bei MS nach wie die ihr Ökosystem immer wieder neu gestalten bzw. nutze die richtigen Quellen.

Gruß,
Peter
Member: Fabian82
Solution Fabian82 Jan 29, 2024 at 20:15:13 (UTC)
Goto Top
Moin,
ich habe die Tage damit rumgespielt.
Ziel war es einen Phish Report Button nicht ganz hinten anzuzeigen, sondern weiter vorne.
Erstmal die Änderungen manuel gemacht und die XML Datei dann kopiert.

Wie du auch schreibst, ist der Namespace aber für jeden User anders.
Ich mach das nun über Powershell.
In der Registry unter HKCU:\SOFTWARE\Microsoft\Office\16.0\Common\CustomUIValidationCache\ sind die ganzen IDs komplett hinterlegt, wenn du dort nach dem ersten Teil der ID suchst, hast du die vollständige ID.
Die ersetze ich dann in dem manuell erstelltem Template und kopiere das rüber.

Klappt zuverlässig und gut. Die User sind nur genervt, dass sie nichts mehr ändern können weil es dann ja überschrieben wird. Aber das find ich gar nicht so verkehrt.

Grüße
Fabian
Member: Dirmhirn
Dirmhirn Jan 29, 2024 at 20:50:35 (UTC)
Goto Top
Sehr gut, danke für den Tipp.
Den Regkey hab ich gesehen, "Cache" hat mich aber abgeschreckt.

Sg Dirm
Member: Dirmhirn
Dirmhirn Feb 20, 2024 at 15:41:15 (UTC)
Goto Top
Hi,
war leider doch nicht das Ende der Geschichte. Wenn man 2 Konten verbunden hat, gibt's auch 2 IDs.
Nur wie findet man de Haupt ID? Denn nur die gilt in den XML Files.
Weißt du wie die IDs heißen?
Sg Dirm
Member: Dirmhirn
Dirmhirn Feb 20, 2024 at 16:18:54 (UTC)
Goto Top
Hi,
war leider doch nicht das Ende der Geschichte. Wenn man 2 Konten verbunden hat, gibt's auch 2 IDs.
Nur wie findet man de Haupt ID? Denn nur die gilt in den XML Files.

Es ist wohl die EmsmdbUID und steht in einer Datei PeopleCach in C:\Users\%username%\AppData\Local\Microsoft\Office\PeopleCache\MAILADresse\PeopleCache
Ist eine txt ohne Endung. Sieht nach json aus.

Sg Dirm
Member: Dirmhirn
Dirmhirn Mar 04, 2024 at 15:28:24 (UTC)
Goto Top
Hi, falls es noch wer benötigt oder Lust hat zu testen. Das ist das Script, mit dem es jetzt funktioniert. Hängt aber leider immernoch von ein paar Dateien und "Beobachtungen" ab. Mal schauen ob es noch Überraschungen gibt, wenn es bei allen läuft.

Es muss für jede Datei ein Template in $env:ProgramData\Office-Outlook-moveJunkReportButton abgelegt werden. Aus den Templates den xmlns:x1 und den group node löschen.

#############################################################################################
# Define variables

# office UI files to modify.
# Filename - Tag id - group id
# create a test file by manually modifying Office UI
# Remove namespace and group node from template file
$filenameTargets = @{
        "olkexplorer.officeUI"=@("TabMail","GroupMailRespond")  
        "olkmailread.officeUI"=@("TabReadMessage","GroupRespond")  
    }

# Product ID, get it from manually created OfficeUI 
$productID = "6046742c-3aee-485e-a4ac-92ab7199db2e"  

# ID for group node. Compare with manually created files.
$attributeIdqFormat = "{0}:Group_${productID}_msgReadGroup_{1}"  

# location of OfficeUI files
$pathTarget = "$env:LOCALAPPDATA\Microsoft\Office"  

# location of templates, will be copied by GPO
$templatePath = "$env:ProgramData\Office-Outlook-moveJunkReportButton"  

# simple log file
$log = "$env:LOCALAPPDATA\Temp\Office-Outlook-moveJunkReportButton.log"  

#############################################################################################

# time stamp for logfile
function Get-TimeStamp { return "[{0:yyyy-MM-dd} {0:HH:mm:ss}]" -f (Get-Date)}  

#Function to get EmsmdbUID
function getEmsmdbUID {

    $emsmdbUID = ''  

    $searcher = [adsisearcher]"(samaccountname=$env:USERNAME)"  
    $userMail = $searcher.FindOne().Properties.mail

    $filePeopleCache = "$env:LOCALAPPDATA\Microsoft\Office\PeopleCache\$userMail\PeopleCache"  
    if (Test-Path $filePeopleCache) {
        $json = Get-Content -Raw -Path $filePeopleCache -Encoding unicode | ConvertFrom-Json
        $emsmdbUID = $json.Get(0).EmsmdbUID

        $emsmdbUID = $emsmdbUID.ToUpper()

    } else {
        # PeopleCache file missing but no output, as PS will return everything, need to change this to a class
    }

    return $emsmdbUID
}


# Function to create or update Office UI customization file
function CreateOrUpdateOfficeUIFile {
    param (
        [string]$templatePath,
        [string]$targetPath,
        [string]$productID,
        [string]$emsmdbUID,
        [string]$attributeIdqFormat,
        [string]$tabeName,
        [string]$groupName

    )

    $namespace = "{0}_{1}" -f $productID, $emsmdbUID  
    # prevent writing file if it is already fixed
    $writeOutput = $false

    if ($templatePath) {
        Write-Output "$(Get-TimeStamp) loading template."  
        # Load template XML
        $xml = [xml](Get-Content -Path $templatePath)
        $writeOutput = $true

    } else {
        Write-Output "$(Get-TimeStamp) loading existing officeUI."  
        # Load template XML
        $xml = [xml](Get-Content -Path $targetPath)
    }

    $xmlRoot = $xml.DocumentElement

    $namespacePrefix = $xmlRoot.GetPrefixOfNamespace($namespace)

    if (!$namespacePrefix) {
        Write-Output "$(Get-TimeStamp) add namespace"  
        
        # search available prefix
        # Define a prefix format
        $prefixFormat = "x{0}"  

        # Find the next available namespace prefix
        $nextPrefix = 1
        while ('' -ne $xmlRoot.GetNamespaceOfPrefix(($prefixFormat -f $nextPrefix))) {  
            $nextPrefix++
        }

        $namespacePrefix = $prefixFormat -f $nextPrefix

        # add namespace
        $xmlRoot.SetAttribute("xmlns:$namespacePrefix", $namespace)  

        $writeOutput = $true

    }

    # format attribute value
    $attributeIdq = $attributeIdqFormat -f $namespacePrefix, $tabName

    $node = $xml.SelectSingleNode("//*[@idQ='$attributeIdq']")  
    if (!$node) {
        Write-Output "$(Get-TimeStamp) create msgReadGroup node"  
        # creat node, if it does not exist
        $nametable = new-object System.Xml.NameTable
        $nsmgr = new-object System.Xml.XmlNamespaceManager($nametable)
        $nsmgr.AddNamespace("mso", "http://schemas.microsoft.com/office/2009/07/customui")  
        $parentNode = $xml.SelectSingleNode("//mso:tab[@idQ='mso:$tabName']", $nsmgr)  

        $node = $parentNode.AppendChild( $xml.CreateElement("mso","group","http://schemas.microsoft.com/office/2009/07/customui") )  
        $node.SetAttribute('idQ', $attributeIdq)  

        $writeOutput = $true
    }


    if ("mso:$groupName" -ne $node.GetAttribute('insertAfterQ')) {  
        Write-Output "$(Get-TimeStamp) fixing insertAfter"  
        # remove insert before
        $node.RemoveAttribute('insertBeforeQ')  
        # add insert after
        $node.SetAttribute('insertAfterQ',"mso:$groupName")  
        $writeOutput = $true
    }

    # create backup of original file
    if (!$templatePath) {
        Copy-Item $targetPath -Destination "$targetPath.bak" -Force  
    }

    if ($writeOutput) {
        # Save XML to target file
        $xml.Save($targetPath)
        Write-Output "$(Get-TimeStamp) File $targetPath updated."  
    } else {
        Write-Output "$(Get-TimeStamp) File already correct"  

    }
}

#function to check if office UI alread yexists
function checkOfficeUI {
    param (
        [string]$filenameTarget,
        [string]$pathTarget,
        [string]$productID,
        [string]$attributeIdqFormat,
        [string]$emsmdbUID,
        [string]$tabName,
        [string]$groupName
    )
    $fileTarget = Join-Path -Path $pathTarget -ChildPath $filenameTarget
    $officeUIExists = Test-Path $fileTarget



    # Check if Office UI file exists
    if (!$officeUIExists) {
        Write-Output "$(Get-TimeStamp) File $fileTarget does not exist. Creating it ..."  

        $templatePath = Join-Path -Path $templatePath -ChildPath "${filenameTarget}_template"  
        
        if (Test-Path $templatePath) {
            CreateOrUpdateOfficeUIFile -templatePath $templatePath -targetPath $fileTarget -productID $productID -emsmdbUID $emsmdbUID -attributeIdqFormat $attributeIdqFormat -tabName $tabName -groupName $groupName
        } else {
            Write-Warning "$(Get-TimeStamp) Missing Tmeplate file $templatePath"  
        }

    } else {
        Write-Output "$(Get-TimeStamp) File $fileTarget exists. Updating it ..."  

        CreateOrUpdateOfficeUIFile -targetPath $fileTarget -productID $productID -emsmdbUID $emsmdbUID -attributeIdqFormat $attributeIdqFormat -tabName $tabName -groupName $groupName

    }
}

Start-Transcript -Path $log

# if we have the Mailbox ID, check each file.
# PS returns any output, taking only the last value from return
$emsmdbUID = getEmsmdbUID

if ($emsmdbUID) {

    Write-Output "$(Get-TimeStamp) Checking $pathTarget ...$emsmdbUID"  
    $filenameTargets.keys | ForEach-Object {    
        checkOfficeUI -filenameTarget $_ -pathTarget $pathTarget -productID $productID -attributeIdqFormat $attributeIdqFormat -emsmdbUID $emsmdbUID -tabName $filenameTargets[$_][0] -groupName $filenameTargets[$_][1]

    }
} else {
    Write-Error "$(Get-TimeStamp) No emesmdbIUD, can not update OfficeUI. File missing or empty."  
}

Stop-Transcript

Sg Dirm
Member: Dirmhirn
Dirmhirn Mar 27, 2024 at 19:38:15 (UTC)
Goto Top
Ganz funktioniert das Script noch nicht bei allen, da bei manchen Usern die UI files existieren, aber der Tabs node fehlt.
Muss ich nochmal überarbeiten.
Sg Dirm
Member: Dirmhirn
Dirmhirn Apr 16, 2024 at 10:00:56 (UTC)
Goto Top
Noch ein Punkt...
Bei mehreren Postfächern, gewinnt das mit der letzten Anpassung der Ribbons pro XML Datei.
Schreiben alle in die gleichen XML files, aber nur wenn die ID stimmt, dann gilt die Datei...
Sg Dirm