Det meste af de sidste 10 år har jeg professionelt arbejdet med emails og der er efterhånden 20 år siden jeg lave min første Qmail mail installation.
Et af de ekstra opgaver i den forbindelse som jeg er løbet ind i, er brugernes sigantur i Outlook, for det er ikke altid ligemeget, hvordan disse ser ud, og der kan for nogle virksomheder endvidere være Compliance krav til disse.
I sommers så jeg et linkedin opslag fra en Markus Gruber, som havde gang i et projekt der består af en powershell script som hedder Set-Outlooksignatures, det så spændene ud og jeg fik også hentet den ned, men det fejlede bigtime i mit setup, henover efteråret kom der nye features til projektet, herunder understøttelse af Exchange Online via GRAPH, hvilket betød at jeg ville give det et "ekstra skud", hvor manualen blev læst lidt grundigere først.

I første omgang virkede det faktisk ikke, jeg fik selv debuggede mig fremtil at det var nogle LDAP queries som fejlede i mit Lab setup, jeg tillod mig at skrive til Markus, som svarrede og vi begynde at debugge I powershell scriptet.
Hen over de sidste 2 uger har der været sendt logfiler og nye versioner af powershell scriptet frem og tilbage, og nu understøtter hans projekt mit lab setup i forbindelse med version 2.4.0

Hvad er så mit lab setup ?
Jo en række virtuelle server, der dækker rollerne som Onprem AD, en AAD Connect server som også har rollen som Modern Hybrid exchange samt  en onprem Exchange server.
Dvs. min outlook klient forbinder direkte til exchange online og den onprem exchange server benyttes kun til "management" af remote mailboxes, hvilket er et setup, jeg finder en del mindre virksomheder som leve i.

Et par note iforbindelse med opsætning af Set-outlooksignatures imod exchange online

1) Man have graph understøttelse ellers kan den ikke sætte siganaturen i owa, man kan vælge at blot køre den i mod onprem ad og man kan få nogle fine signature i outlook, dog ikke i owa.

Markus har lavet en fin dokumentation af hvordan denne APP register i azuread skal opsættes og det er heldigvis ikke voldsomme rettigheder appen skal have, da alle er af typen Delegated, med der skal forsat gives admin Consent for et par af dem.

Authentication skal opsættes til http://localhost samt Allow Public Client flows, sættes til yes.


Er man søde ved brugerne hopper man efterfølgende over i Enterprise applications og finder appen igen for at under Permissions at giver en Grand admin consent der også, så slipper brugerne for en "browser popup", hvor de skal give adgang.

 

Derefter skal Application (client) ID som findes i app-registeren erstattes i "default graph config.ps1" variablen $GraphClientID
Filen findes i mappen "config"

2) lave outlook signature templates

Næste opgave er at tilrette de templates som kommer med scriptet i mappen Templates\Signatures DOCX  hvilket er mega nemt, for det er word filer som fungere som templates, det er nærmest blot åben og ret, dvs. det vil alm. kontor personale kunne varetage dette efter en kort indkørring i variablerne.


Skal man virkelig lave flotte signature som står skarp på alle pladforme, vil jeg dog anbefale man i stedet ændre set-outlooksignatures til at benytte de "html" templates den også undersøtter og koder det i html, men word versionen er nok til mig for nu.

3) Test

Herefter skal scriptet blot køres i alm. bruger kontext (Set-OutlookSignatures.ps1'-graphonly $true ), og 3,2,1 der er Signatur i Outlook samt exchange online owa, det er da bare nemt :-)
Eksemple på en hurtig tilrette version, hvor langt de fleste felter kommer fra aad data

4) Deployment til brugerne

Personlig ønsker jeg ikke at auto opdater signaturen i mit miljø, for man kan kunne godt ligge den ind i en form for auto kørsel.
Jeg har i stedet pakken den ind via PSAppDeployToolkit, sådan jeg kan sende den ud på alle de lokale computer, og har i forbindelse med deployment lavet en genvej i start menuen til Set-Outlooksignatures.ps1

Powershellen i min Deployment-applications.ps1 består af 4 dele

a) Oprettelse af mappe i File strukture.

$InstallDestinationFolder = $env:programfiles + "\Set-OutlookSignatures"
if(Test-Path $InstallDestinationFolder)
{
## installtions mappe findes
Remove-Item $InstallDestinationFolder -Recurse -Force
new-Item -Path $InstallDestinationFolder -ItemType Directory -Force


}
else
{
New-Item -Path $InstallDestinationFolder -ItemType Directory
}

b) Kopiering af filer fra installations mappen og ind i file strukturen

  Copy-Item -LiteralPath "$($dirfiles)" -Destination $InstallDestinationFolder -Recurse

c )Oprettelse af en genvej til startmenuen. ( eksemple på oprettelse af genvej ligger med i set-outlooksignatures zip filen, ligeledes understøttende grafik.)

 $WshShell = New-Object -ComObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut((Join-Path -Path $([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::CommonStartMenu)) -ChildPath 'Set Outlook signatures.lnk'))
$Shortcut.WorkingDirectory = $InstallDestinationFolder
$Shortcut.TargetPath = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe'
$Shortcut.Arguments = "-Command ""& '$($InstallDestinationFolder)\files\Set-OutlookSignatures.ps1' -graphonly $true """
$Shortcut.IconLocation = "$($InstallDestinationFolder)\files\logo\Set-OutlookSignatures Icon.ico"
$Shortcut.Description = 'Set Outlook signatures using Set-OutlookSignatures.ps1'
$Shortcut.WindowStyle = 1 # 1 = undefined, 3 = maximized, 7 = minimized
$Shortcut.Hotkey = ''
$Shortcut.Save()

d )Sync af nye templates ud på klienten, i tilfælde af at det var kommet ekstra til efterfølgende.

## sync ekstra / nye templates ned
$TemplateServer = "\\fileserver"
$TemplateShare="\Set-OutlookSignatures"

if(Test-Path "$($TemplateServer)$($TemplateShare)")
{
$tempatesFolders = Get-ChildItem "$($InstallDestinationFolder)\files\templates"
foreach($templateType in $tempatesFolders)
{
# $templateType.FullName
# "$($TemplateServer)$($TemplateShare)\$templateType"
if("$($TemplateServer)$($TemplateShare)\$templateType")
{
Copy-Item "$($TemplateServer)$($TemplateShare)\$templateType" $templateType.FullName -Recurse
}
}
} 

Efter færdig deployement man man nu søge "set outlook signatures frem i start menu'en på windows og få opbygget en standard signatur udfra sine data i AD

 

 Hvad løser set-outlooksignatures IKKE, jo microsoft mangler forsat at tillader os at deploy en signatur som kan ramme outlook.app på android og Ios enheder, men det skulle jo være på vej.....
Ekstra NOTE: at opdater en allerede sat signatur i OWA, har nogle bugs pt, hvilket mange forventer skyldes microsoft længe ventet Outlook signatur roaming opdatering som skulle få mobil telefonerne med, derfor kan owa sigantur opdateringen godt gå i stå, man kan dog omgå problemet ved at manuelt gå ind og fjerne den allerede oprettet signatur, vente 5 miniutter og køre scriptet igen.

Microsoft sendt out off band patch afsted til exchange familien den 3.3.2021 (KB5000871) og mine første 2 exchange server der skulle opdateres gik jo egentlig pæt fint, Men den sidste gav nogle udfordringer. :-(

1) jeg havde selv sat mig i en dårlig situation, serveren var gået siteway med nogle windows opdateringer og havde derfor fået lov til at stå Upatched i en længere priode, ja velkommen til den virkelige verden....

Dvs. serveren skulle løftes fra CU6 til CU19 + opdatering, dvs. der skulle tilføjes C++ 2013 og .net 4.8 til serveren og gjore jeg det på en gang ville det være en ikke supporteret manøver, men som microsoft skriver, noget som godt kan lade sig gørre.

Selve CU19 køre fint på indtil sidste step. BANG....

Error:
The following error was generated when "$error.Clear();
$dependentAssemblyGeneratorExePath = [System.IO.Path]::Combine($RoleInstallPath, "bin", "DependentAssemblyGenerator.exe");
$exchangeBinPath = [System.IO.Path]::Combine($RoleInstallPath, "bin");
$clientAccessPath = [System.IO.Path]::Combine($RoleInstallPath, "ClientAccess");
$sharedWebConfig = [System.IO.Path]::Combine($RoleInstallPath, "ClientAccess", "SharedWebConfig.config");

$a = &"$dependentAssemblyGeneratorExePath" -exchangePath "$exchangeBinPath" -exchangePath "$clientAccessPath" -configFile "$sharedWebConfig";
$allOutput = @();
$a | % { $allOutput += $_ };
Write-ExchangeSetupLog -Info ($allOutput -join "`r`n");
Stop-SetupService -ServiceName WAS;
Start-SetupService -ServiceName W3SVC;
" was run: "System.Management.Automation.RemoteException".

System.Management.Automation.RemoteException: System.UnauthorizedAccessException: Access to the path 'c:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\SharedWebConfig.config' is denied.

 Jeg genkøre engeligt CU 19 og denne gang - afslutter den fint :-)

OWA og ecp checkes og serveren ser frisk og rask ud - lige klar til at installer KB5000871

 OG her skulle jeg så nok være stoppet for den aften ........

Underførste installation af KB5000871 - kørte der en anden windows opdatering, som var frigivet efter den genstart jeg lavede efter CU 19, så jeg endte med alle exchange services disabled :-(
Enable dem igen, og rename tilhørrende xml filer under Exchangestuplogs - så var jeg klar igen.
Enu en kørsel - denne gang døde KB5000871 i en File som den sagde var låst :-(
KB5000871 lave self rollback...

jeg genstarter serveren endu engang - men glemmer at checke at alle services er i luften igen.
KB5000871 installeres på ny og jeg mener faktisk at den går ok. ( jubiiiii )
jeg genstarter serveren og skal til at teste owa, ecp mm. og intet svarer :-(
double checker servicesne og ingen af disse er tændt....

MSExchangeADTopology services vil ikke starter, den smider en meget grim fejl...... a'la mr watson
Der var ikke rigtig nogle gode svar på hvad at gøre, udover i denne tråd
Mit valg var mellem at dømme exchange servere død og lave den store recovery øvelse, eller prøve følgende - som med 100% sikkerhed er IKKE SUPPORTERET ! som står i tråden
CU10 var blot CI19 og KB'erne var KB5000871 

1) Ensure all of the Exchange services and supporting services (IIS, IISAdmin, etc.) are stopped and disabled.
2) From the current version media (Exchange 2016 CU10, in our case) run the EXCHANGESERVER.msi with the /fa flags (msiexec.exe /fa EXCHANGESERVER.msi ). This will force the installation to replace all the binaries with the version from the install media without updating the registry.
3) Apply all the necessary patches in order (KB4340731 and then KB4459266, in our case).
4) Re-enable the Exchange services and additional dependent services and reboot the server
5) Fix-up and start any services that did not start. Probably some services won't start due to dependent services being disabled
6) All the IIS sits will be broke at this point, ECP, ActiveSync, OWA and Outlook won't work and the Exchange PowerShell will report errors. To resolve this run the UpdateCas.ps1 script from the Exchange install.
7) Finally find all the web.config and SharedWebConfig.config files in the ..\Exchange Server\V15\ClientAccess\ folder and ..\Exchange Server\V15\FrontEnd\HttpProxy\ folder. These files will need to be updated to replace %ExchangeInstallDir% with the actual install location (C:\Program Files\Microsoft\Exchange Server\V15\ in our case). These files were not updated by the CustomAction that is executed by the Setup.exe. This step is skipped when the MSI is run manually.
8) Re-apply any custom changes to the IIS sites (i.e. http to https redirection for OWA, if you're doing that)

Det lykkes mig faktisk at få serven til at starte igen MSExchangeADTopology  servicen kunne nu starte, dog kom OWA, ECP aldrig rigtig i luften igen, Active-sync kørte ustabilt, men serveren var nok i luften til at jeg kunne efterfølgende lave move-maiibox over på en anden exchange server, hvorefter denne blev nedlagt....

Men en laaaaang aften med frustrationer fra tid til anden.....

2 VIGTIGE TING

Kør ikke exchange server med mindre at man har tiden og resourcen til at hele tiden følge CU opdateringer !
Kan man ikke det, er man meget bedre ved at få alle mailboxes flyttet til exchange Online, hvor MS varetager alt bøvlet ;-)

 Jeg førsøge øvrigt at fixe de shared config filer via.
https://docs.microsoft.com/en-us/exchange/troubleshoot/client-connectivity/event-1309-code-3005-cannot-access-owa-ecp

DependentAssemblyGenerator.exe -exchangePath "E:\Program Files\Microsoft\Exchange Server\V15\bin" -exchangePath "C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess" -configFile "C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\SharedWebConfig.config"
DependentAssemblyGenerator.exe -exchangePath "E:\Program Files\Microsoft\Exchange Server\V15\bin" -exchangePath "C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy" -configFile "C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\SharedWebConfig.config"

UPDATE :-)

 Jeg fik faktisk serveren til at køre igen, jeg begyndte at læse hvad der stod i eventliggen og indså at en del af mit problem var beskrvet her: You receive a Server Error while browsing the Exchange EWS or Autodiscover sites (microsoft.com) og ikke kun i Event ID 1309 and you can't access OWA and ECP after you install Exchange Server 2016 or Exchange Server 2013 - Exchange | Microsoft Docs ( det stod faktisk også som del af punkt 7  LoL, det er hvad der sker, når server opdateres langt ud på natten)

Og ganske rigtigt havde jeg masser af %Exchangeinstalldir% som skulle opdateret til den direkte path, sjovt nok var jeg på jagt efter dette, samme aften som problemet opstod, men stoppede da opdatering af "sharedwebconfig.config" ikke var nok, ligeledes rettet jeg det også i IIS'en, men havde ikke lige indset at der var en rætte andre web.condig filer.

Rootcause til ovenståender er at micrsoft i forbindelse med en tidligere CU som jeg har sprunget over, har udskiftet %exchangeInstallDir% med den absolutte sti til filerne, den forandring havde jeg så ikke fået med :-(   jeg
løsning er blot for hver Eventid id 1310 at taget web.config filen nævnt heri og fide %exchangeinstalldir% ændre disse, nogle af dem har mange linjer der skal opdateres andre er der kun 1 i bunden. :-)  det kan godt tage et par genstarts før man har fundet dem alle, jeg har dog se andre personer publicer powershell scripts der rettede dette for dem efterfølgende.