631 lines
25 KiB
Markdown
631 lines
25 KiB
Markdown
# 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>[^=]+)=(?<value>.*)$') {
|
|
$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 = '<div style="font-size: 14px; color: #ffffff;">[JOB] | [DEPARTMENT]</div>'
|
|
$pattern = [Regex]::Escape($searchString)
|
|
$replacement = '<div style="font-size: 14px; color: #ffffff;">[DEPARTMENT]</div>'
|
|
$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 = @"
|
|
<Window
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
Title="E-Mail Signaturen"
|
|
WindowStyle="None"
|
|
ResizeMode="NoResize"
|
|
Background="#262626">
|
|
|
|
<Window.Resources>
|
|
|
|
<!-- Keine Hover-Effekte, nur normal/pressed für den X-Button -->
|
|
<Style x:Key="CloseButtonStyle" TargetType="Button">
|
|
<Setter Property="OverridesDefaultStyle" Value="True"/>
|
|
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
|
|
<Setter Property="Foreground" Value="#FFFFFF"/>
|
|
<Setter Property="Background" Value="Transparent"/>
|
|
<Setter Property="BorderBrush" Value="Transparent"/>
|
|
<Setter Property="FontWeight" Value="Bold"/>
|
|
<Setter Property="FontSize" Value="16"/>
|
|
<Setter Property="Width" Value="30"/>
|
|
<Setter Property="Height" Value="30"/>
|
|
<Setter Property="Padding" Value="0"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<!-- Wir definieren ein Custom Template, ohne Hover-Trigger -->
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="Button">
|
|
<Border x:Name="border"
|
|
Background="{TemplateBinding Background}"
|
|
BorderBrush="{TemplateBinding BorderBrush}"
|
|
BorderThickness="{TemplateBinding BorderThickness}">
|
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<!-- Nur Pressed-Trigger (optional) -->
|
|
<Trigger Property="IsPressed" Value="True">
|
|
<Setter TargetName="border" Property="Background" Value="#444444"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- Ab hier definieren wir ein eigenes ControlTemplate für OK/Abbrechen-Buttons -->
|
|
<Style x:Key="FancyButtonStyle" TargetType="Button" BasedOn="{x:Null}">
|
|
<!-- Wichtig: eigene Vorlage, damit wir Windows-Standard nicht haben -->
|
|
<Setter Property="OverridesDefaultStyle" Value="True"/>
|
|
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
|
|
|
|
<!-- Normal-Attribute -->
|
|
<Setter Property="Foreground" Value="#FFFFFF"/>
|
|
<Setter Property="Background" Value="#3A3A3A"/>
|
|
<Setter Property="BorderBrush" Value="#555555"/>
|
|
<Setter Property="BorderThickness" Value="1"/>
|
|
<Setter Property="FontWeight" Value="Bold"/>
|
|
<Setter Property="FontSize" Value="12"/>
|
|
<Setter Property="Margin" Value="5,0,5,0"/>
|
|
<Setter Property="Padding" Value="6,3,6,3"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="Button">
|
|
<!-- Rahmen in Form einer Border -->
|
|
<Border x:Name="border"
|
|
Background="{TemplateBinding Background}"
|
|
BorderBrush="{TemplateBinding BorderBrush}"
|
|
BorderThickness="{TemplateBinding BorderThickness}">
|
|
<!-- Hier liegt der eigentliche Button-Inhalt -->
|
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<!-- Hover: Hintergrund #FDC100, Schrift #000000 -->
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="border" Property="Background" Value="#FDC100"/>
|
|
<Setter Property="Foreground" Value="#000000"/>
|
|
</Trigger>
|
|
<!-- Pressed: Hintergrund #C77E00, Schrift #FFFFFF -->
|
|
<Trigger Property="IsPressed" Value="True">
|
|
<Setter TargetName="border" Property="Background" Value="#C77E00"/>
|
|
<Setter Property="Foreground" Value="#FFFFFF"/>
|
|
</Trigger>
|
|
<!-- Deaktiviert -->
|
|
<Trigger Property="IsEnabled" Value="False">
|
|
<Setter TargetName="border" Property="Background" Value="#707070"/>
|
|
<Setter Property="Foreground" Value="#AAAAAA"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- RadioButton-Style -->
|
|
<Style TargetType="RadioButton">
|
|
<Setter Property="Foreground" Value="#FFFFFF"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="RadioButton">
|
|
<StackPanel Orientation="Horizontal" Margin="0,5,0,5">
|
|
<Border Width="16" Height="16"
|
|
BorderBrush="#3F3F3E"
|
|
BorderThickness="2"
|
|
CornerRadius="8" Margin="0,0,5,0">
|
|
<Ellipse x:Name="EllipseFill" Fill="Transparent"/>
|
|
</Border>
|
|
<ContentPresenter/>
|
|
</StackPanel>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsChecked" Value="True">
|
|
<Setter TargetName="EllipseFill" Property="Fill" Value="#FDC100"/>
|
|
</Trigger>
|
|
<Trigger Property="IsEnabled" Value="False">
|
|
<Setter TargetName="EllipseFill" Property="Fill" Value="Gray"/>
|
|
<Setter Property="Foreground" Value="Gray"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- ListView-Style: dunkel, bei deaktiviert -> Schrift grau -->
|
|
<Style TargetType="ListView" x:Key="UserListStyle">
|
|
<Setter Property="Background" Value="#2F2F2E"/>
|
|
<Setter Property="Foreground" Value="#FFFFFF"/>
|
|
<Style.Triggers>
|
|
<Trigger Property="IsEnabled" Value="False">
|
|
<Setter Property="Foreground" Value="Gray"/>
|
|
<Setter Property="Background" Value="#2F2F2E"/>
|
|
</Trigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
|
|
<!-- ListViewItem-Style -->
|
|
<Style TargetType="ListViewItem" x:Key="ItemStyle">
|
|
<Setter Property="Background" Value="#2F2F2E"/>
|
|
<Setter Property="Foreground" Value="#FFFFFF"/>
|
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
|
<Style.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter Property="Background" Value="#3A3A3A"/>
|
|
</Trigger>
|
|
<DataTrigger Binding="{Binding IsEnabled,
|
|
RelativeSource={RelativeSource AncestorType=ListView}}" Value="False">
|
|
<Setter Property="Foreground" Value="Gray"/>
|
|
<Setter Property="Background" Value="#2F2F2E"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
|
|
<!-- ScrollViewer-Style: kein Weiß -->
|
|
<Style TargetType="ScrollViewer">
|
|
<Setter Property="Background" Value="#2F2F2E"/>
|
|
</Style>
|
|
</Window.Resources>
|
|
|
|
<Grid x:Name="RootGrid">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/> <!-- Eigener Titelbalken -->
|
|
<RowDefinition Height="Auto"/> <!-- Überschrift + Radiobuttons -->
|
|
<RowDefinition Height="Auto"/> <!-- ListView -->
|
|
<RowDefinition Height="Auto"/> <!-- Buttons -->
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- Titelbalken (mit "X" rechts) -->
|
|
<Grid Grid.Row="0" x:Name="TitleBar" Background="#444444">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
</Grid.ColumnDefinitions>
|
|
<!-- Titel hier -->
|
|
<TextBlock Text="E-Mail Signaturen"
|
|
Foreground="#FFFFFF"
|
|
VerticalAlignment="Center"
|
|
Margin="10,0,0,0"/>
|
|
<Button x:Name="btnClose" Grid.Column="1"
|
|
Style="{StaticResource CloseButtonStyle}"
|
|
Content="✕"
|
|
HorizontalAlignment="Right"
|
|
Margin="0,0,10,0"/>
|
|
</Grid>
|
|
|
|
<!-- Überschrift + Radiobuttons -->
|
|
<StackPanel Orientation="Vertical" Grid.Row="1" Margin="10">
|
|
<TextBlock Text="Signaturen erstellen für ..."
|
|
Foreground="#FFFFFF"
|
|
FontWeight="Bold"
|
|
FontSize="16"
|
|
Margin="0,0,0,10"/>
|
|
<RadioButton x:Name="rbAlle" Content="alle Mitarbeiter" />
|
|
<RadioButton x:Name="rbAuswahl" Content="den ausgewählten Mitarbeiter" />
|
|
</StackPanel>
|
|
|
|
<!-- Liste mit Nutzern (max 300px hoch, scrollt bei Bedarf) -->
|
|
<ListView x:Name="lvUsers" Style="{StaticResource UserListStyle}"
|
|
ItemContainerStyle="{StaticResource ItemStyle}"
|
|
Grid.Row="2" Margin="10" MaxHeight="300">
|
|
<ListView.ItemTemplate>
|
|
<DataTemplate>
|
|
<StackPanel Orientation="Horizontal">
|
|
<CheckBox IsChecked="{Binding Selected}" Margin="5,0,5,0"/>
|
|
<TextBlock Text="{Binding DisplayText}" VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
</DataTemplate>
|
|
</ListView.ItemTemplate>
|
|
</ListView>
|
|
|
|
<!-- Buttons OK / Abbrechen -->
|
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="3" Margin="10">
|
|
<Button x:Name="btnOK" Style="{StaticResource FancyButtonStyle}" Content="OK" Width="80" Margin="0,0,10,0"/>
|
|
<Button x:Name="btnCancel" Style="{StaticResource FancyButtonStyle}" Content="Abbrechen" Width="80"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
</Window>
|
|
"@
|
|
|
|
[xml]$xml = $XAML
|
|
$reader = New-Object System.Xml.XmlNodeReader $xml
|
|
$Window = [Windows.Markup.XamlReader]::Load($reader)
|
|
|
|
# Fenster-Einstellungen
|
|
$Window.Width = 400
|
|
$Window.SizeToContent = 'Height'
|
|
$Window.WindowStartupLocation = 'CenterScreen'
|
|
$Window.MaxHeight = [System.Windows.SystemParameters]::PrimaryScreenHeight * 0.8
|
|
|
|
# Elemente holen
|
|
$TitleBar = $Window.FindName('TitleBar')
|
|
$btnClose = $Window.FindName('btnClose')
|
|
$rbAlle = $Window.FindName('rbAlle')
|
|
$rbAuswahl = $Window.FindName('rbAuswahl')
|
|
$lvUsers = $Window.FindName('lvUsers')
|
|
$btnOK = $Window.FindName('btnOK')
|
|
$btnCancel = $Window.FindName('btnCancel')
|
|
|
|
# Beim Start: "alle Mitarbeiter" -> Liste grau
|
|
$rbAlle.IsChecked = $true
|
|
$lvUsers.IsEnabled = $false
|
|
|
|
$rbAlle.Add_Checked({
|
|
$lvUsers.IsEnabled = $false
|
|
})
|
|
$rbAuswahl.Add_Checked({
|
|
$lvUsers.IsEnabled = $true
|
|
})
|
|
|
|
# Datenquelle
|
|
$lvUsers.ItemsSource = $global:AllUsers
|
|
|
|
# Funktion zur Aktualisierung der RadioButton-Beschriftung
|
|
function UpdateRbAuswahlContent {
|
|
$count = ($global:AllUsers | Where-Object { $_.Selected -eq $true }).Count
|
|
if ($count -ge 2) {
|
|
$rbAuswahl.Content = "die ausgewählten Mitarbeiter"
|
|
}
|
|
else {
|
|
$rbAuswahl.Content = "den ausgewählten Mitarbeiter"
|
|
}
|
|
}
|
|
|
|
# Event-Handler für Check/Uncheck in der Liste
|
|
$lvUsers.AddHandler(
|
|
[System.Windows.Controls.Primitives.ButtonBase]::ClickEvent,
|
|
[System.Windows.RoutedEventHandler]{
|
|
UpdateRbAuswahlContent
|
|
},
|
|
$true
|
|
)
|
|
|
|
# Titelbalken "Drag" (Fenster verschieben)
|
|
$TitleBar.Add_MouseLeftButtonDown({
|
|
if ($_.LeftButton -eq [System.Windows.Input.MouseButtonState]::Pressed) {
|
|
try {
|
|
$Window.DragMove()
|
|
} catch {}
|
|
}
|
|
})
|
|
|
|
# "X"-Button oben rechts
|
|
$btnClose.Add_Click({
|
|
$Script:SelectedUsers = $null
|
|
$Window.Close()
|
|
})
|
|
|
|
# OK-/Abbrechen-Logik
|
|
$Script:SelectedUsers = $null
|
|
$btnOK.Add_Click({
|
|
if ($rbAlle.IsChecked -eq $true) {
|
|
$Script:SelectedUsers = $global:AllUsers
|
|
} else {
|
|
$Script:SelectedUsers = $global:AllUsers | Where-Object { $_.Selected -eq $true }
|
|
}
|
|
$Window.Close()
|
|
})
|
|
$btnCancel.Add_Click({
|
|
$Script:SelectedUsers = $null
|
|
$Window.Close()
|
|
})
|
|
|
|
# UI anzeigen
|
|
$null = $Window.ShowDialog()
|
|
|
|
# Falls abgebrochen oder geschlossen
|
|
if (-not $Script:SelectedUsers) {
|
|
Write-HostIfDebug "Abgebrochen. Keine Signaturen erzeugt."
|
|
return
|
|
}
|
|
|
|
# Signaturen erstellen
|
|
Generate-SignaturesForUsers -selectedUsers $Script:SelectedUsers
|
|
``` |