# Requirements 1. ".env" Datei im gleichen Verzeichnis, wie das, in dem das Powershell Script gesichert wird. 2. "template.txt", "template.html", "template.rtf" ebenfalls in dem jeweiligen Verzeichnis ablegen. ## Aufbau: .env Datei ``` AD_OUPath=OU=...,OU=...,OU=...,DC=contoso,DC=org SIGNATURE_PATH=C:\Scripts\Sinatures DEBUG=0 ``` Die Werte sind Beispielwerte und entsprechend anzupassen. Debug gibt Rückmeldungen in der Powershell. ## Aufbau: template Dateien In den Templates werden Platzhalter genutzt um die Variablen zu ersetzen mit den Werten aus dem AD. [VORNAME] [NACHNAME] [JOB] [DEPARTMENT] [PHONE] [PLAIN_PHONE] [EMAIL] Ich selbst habe den Teil innerhalb der Templates so gestaltet, dass es "[JOB] | [DEPARTMENT]" gibt. Wenn ein User keine JOB Bezeichnung im AD hat, würde das automatisch ersetzt werden durch "[DEPARTMENT]". Da ich auch Links beim Klicken auf Icons nutze, muss die Telefonnummer etwas angepasst werden in der html Template Datei. Dafür habe ich im "tel:" Bereich ein "[PLAIN_PHONE]" gesetzt. ## Powershell Script: ```powershell Canvas [Console]::OutputEncoding = [Text.Encoding]::UTF8 ############################################################################### # 0) FUNKTION ZUR DEBUG-AUSGABE ############################################################################### function Write-HostIfDebug { param( [Parameter(Mandatory=$true)] [string]$Message, # Der Typ hier ist entfernt, damit null oder eine valide Farbe möglich ist. $ForegroundColor ) if ($Env:DEBUG -eq "1") { if ($ForegroundColor) { Write-Host $Message -ForegroundColor $ForegroundColor } else { Write-Host $Message } } } ############################################################################### # 1) SIGNATUREN-LOGIK ############################################################################### function ConvertPhoneForHtml($phone) { if (![string]::IsNullOrEmpty($phone)) { $phone = $phone -replace " ", " ​" $phone = $phone -replace "-", " ​- ​" } return $phone } function ConvertEmailForHtml($mail) { if (![string]::IsNullOrEmpty($mail)) { $mail = $mail -replace "\\.", ".​" $mail = $mail -replace "@", "@​" $mail = $mail -replace "-", "-​" } return $mail } # .env einlesen $envFile = Join-Path $PSScriptRoot '.env' if (Test-Path $envFile) { Get-Content -Path $envFile | ForEach-Object { if ($_ -match '^(?[^=]+)=(?.*)$') { $key = $Matches['key'] $value = $Matches['value'] Set-Item -Path "Env:$key" -Value $value } } } else { Write-HostIfDebug ".env-Datei wurde nicht gefunden. Bitte stelle sicher, dass sie im gleichen Verzeichnis liegt." return } # Pfade aus .env $ouPath = $Env:AD_OUPath $signaturePath = $Env:SIGNATURE_PATH if (!$ouPath) { Write-HostIfDebug "Bitte überprüfe, ob in der .env-Datei die Variable 'AD_OUPath' eingetragen ist." return } if (![string]::IsNullOrEmpty($signaturePath)) { if (!(Test-Path $signaturePath)) { Write-HostIfDebug "Der Pfad '$signaturePath' existiert nicht. Bitte überprüfen." return } } else { Write-HostIfDebug "Bitte überprüfe, ob in der .env-Datei die Variable 'SIGNATURE_PATH' eingetragen ist." return } Write-HostIfDebug "Suche nach Benutzern in der OU: $ouPath..." # Benutzer holen (und sortieren) $users = Get-ADUser -Filter * -SearchBase $ouPath -Properties cn, givenName, sn, telephoneNumber, mail, title, department Write-HostIfDebug "Gefundene Benutzer:`n" $global:AllUsers = $users | Sort-Object -Property sn, givenName | ForEach-Object { [PSCustomObject]@{ Selected = $false CN = $_.cn ADUser = $_ DisplayText = if ($_.sn -and $_.givenName) { "$($_.sn), $($_.givenName) ($($_.cn))" } else { $_.cn } } } function Generate-SignaturesForUsers($selectedUsers) { foreach ($item in $selectedUsers) { $user = $item.ADUser $cn = $user.cn $givenName = $user.givenName $sn = $user.sn $originalPhone = $user.telephoneNumber $originalEmail = $user.mail $plainPhone = if (![string]::IsNullOrEmpty($originalPhone)) { $originalPhone -replace '^0+', '' } else { "" } $convertedPhone = ConvertPhoneForHtml($originalPhone) $convertedEmail = ConvertEmailForHtml($originalEmail) $jobTitle = $user.title $department = $user.department Write-HostIfDebug "-----------------------------------" Write-HostIfDebug "CN : $cn" Write-HostIfDebug "Vorname : $($givenName)" Write-HostIfDebug "Nachname : $($sn)" Write-HostIfDebug "Telefon (orig): $($originalPhone)" Write-HostIfDebug "Telefon (HTML): $($convertedPhone)" Write-HostIfDebug "plain_phone : $($plainPhone)" Write-HostIfDebug "E-Mail (orig) : $($originalEmail)" Write-HostIfDebug "E-Mail (HTML) : $($convertedEmail)" Write-HostIfDebug "Job (Title) : $($jobTitle)" Write-HostIfDebug "Abteilung : $($department)" # 1) HTML $templateFilePath = Join-Path $PSScriptRoot 'template.html' if (!(Test-Path $templateFilePath)) { Write-HostIfDebug "Vorlage 'template.html' wurde nicht gefunden, bitte prüfe den Pfad." -ForegroundColor Red return } $signatureHtml = Get-Content -Path $templateFilePath -Raw if ([string]::IsNullOrEmpty($jobTitle)) { $searchString = '
[JOB] | [DEPARTMENT]
' $pattern = [Regex]::Escape($searchString) $replacement = '
[DEPARTMENT]
' $signatureHtml = $signatureHtml -replace $pattern, $replacement } # E-Mail if ($originalEmail) { $pattern = 'href="mailto:\[EMAIL\]"' $replacement = 'href="mailto:' + $originalEmail + '"' $signatureHtml = $signatureHtml -replace $pattern, $replacement $pattern = '\[EMAIL\]' $replacement = $convertedEmail $signatureHtml = $signatureHtml -replace $pattern, $replacement } else { $pattern = 'href="mailto:\[EMAIL\]"' $replacement = 'href="mailto:"' $signatureHtml = $signatureHtml -replace $pattern, $replacement $pattern = '\[EMAIL\]' $replacement = '' $signatureHtml = $signatureHtml -replace $pattern, $replacement } # Phone if ($plainPhone) { $pattern = 'href="tel:\+49\[PLAIN_PHONE\]"' $replacement = 'href="tel:+49' + $plainPhone + '"' $signatureHtml = $signatureHtml -replace $pattern, $replacement $pattern = '\[PHONE\]' $replacement = $convertedPhone $signatureHtml = $signatureHtml -replace $pattern, $replacement } else { $pattern = 'href="tel:\+49\[PHONE\]"' $replacement = 'href="tel:"' $signatureHtml = $signatureHtml -replace $pattern, $replacement $pattern = '\[PHONE\]' $replacement = '' $signatureHtml = $signatureHtml -replace $pattern, $replacement } # Weitere Platzhalter $signatureHtml = $signatureHtml -replace '\[VORNAME\]', $givenName $signatureHtml = $signatureHtml -replace '\[NACHNAME\]', $sn $signatureHtml = $signatureHtml -replace '\[JOB\]', $jobTitle $signatureHtml = $signatureHtml -replace '\[DEPARTMENT\]', $department $signatureHtml = $signatureHtml -replace '\[PLAIN_PHONE\]', $plainPhone $filename = "${cn}.htm" $outputPath = Join-Path $signaturePath $filename Set-Content -Path $outputPath -Value $signatureHtml -Encoding UTF8 Write-HostIfDebug "Signatur (HTML) für '$($cn)' unter: $outputPath erstellt." -ForegroundColor Green # 2) TXT (wenn vorhanden) $templateTxtFilePath = Join-Path $PSScriptRoot 'template.txt' if (Test-Path $templateTxtFilePath) { $signatureTxt = Get-Content -Path $templateTxtFilePath -Raw if ([string]::IsNullOrEmpty($jobTitle)) { $searchString = '[JOB] | [DEPARTMENT]' $pattern = [Regex]::Escape($searchString) $replacement = '[DEPARTMENT]' $signatureTxt = $signatureTxt -replace $pattern, $replacement } if ($originalEmail) { $signatureTxt = $signatureTxt -replace '\[EMAIL\]', $originalEmail } else { $signatureTxt = $signatureTxt -replace '\[EMAIL\]', '' } if ($originalPhone) { $signatureTxt = $signatureTxt -replace '\[PHONE\]', $originalPhone } else { $signatureTxt = $signatureTxt -replace '\[PHONE\]', '' } if ($plainPhone) { $signatureTxt = $signatureTxt -replace '\[PLAIN_PHONE\]', $plainPhone } else { $signatureTxt = $signatureTxt -replace '\[PLAIN_PHONE\]', '' } $signatureTxt = $signatureTxt -replace '\[VORNAME\]', $givenName $signatureTxt = $signatureTxt -replace '\[NACHNAME\]', $sn $signatureTxt = $signatureTxt -replace '\[JOB\]', $jobTitle $signatureTxt = $signatureTxt -replace '\[DEPARTMENT\]', $department $txtFilename = "${cn}.txt" $txtOutputPath = Join-Path $signaturePath $txtFilename Set-Content -Path $txtOutputPath -Value $signatureTxt -Encoding UTF8 Write-HostIfDebug "Signatur (TXT) für '$($cn)' unter: $txtOutputPath erstellt." -ForegroundColor Green } # 3) RTF (wenn vorhanden) $templateRtfFilePath = Join-Path $PSScriptRoot 'template.rtf' if (Test-Path $templateRtfFilePath) { $signatureRtf = Get-Content -Path $templateRtfFilePath -Raw if ([string]::IsNullOrEmpty($jobTitle)) { $searchString = '[JOB] | [DEPARTMENT]' $pattern = [Regex]::Escape($searchString) $replacement = '[DEPARTMENT]' $signatureRtf = $signatureRtf -replace $pattern, $replacement } if ($originalEmail) { $signatureRtf = $signatureRtf -replace '\[EMAIL\]', $originalEmail } else { $signatureRtf = $signatureRtf -replace '\[EMAIL\]', '' } if ($originalPhone) { $signatureRtf = $signatureRtf -replace '\[PHONE\]', $originalPhone } else { $signatureRtf = $signatureRtf -replace '\[PHONE\]', '' } if ($plainPhone) { $signatureRtf = $signatureRtf -replace '\[PLAIN_PHONE\]', $plainPhone } else { $signatureRtf = $signatureRtf -replace '\[PLAIN_PHONE\]', '' } $signatureRtf = $signatureRtf -replace '\[VORNAME\]', $givenName $signatureRtf = $signatureRtf -replace '\[NACHNAME\]', $sn $signatureRtf = $signatureRtf -replace '\[JOB\]', $jobTitle $signatureRtf = $signatureRtf -replace '\[DEPARTMENT\]', $department $rtfFilename = "${cn}.rtf" $rtfOutputPath = Join-Path $signaturePath $rtfFilename Set-Content -Path $rtfOutputPath -Value $signatureRtf -Encoding Default Write-HostIfDebug "Signatur (RTF) für '$($cn)' unter: $rtfOutputPath erstellt." -ForegroundColor Green } Write-HostIfDebug "-----------------------------------" } Write-HostIfDebug "Fertig! Signaturen wurden erstellt." } ############################################################################### # 2) WPF-UI + DRAG MOVE ############################################################################### Add-Type -AssemblyName PresentationCore,PresentationFramework $XAML = @"