windows-printer-migrator/PrinterMigrator.ps1

1331 lines
52 KiB
PowerShell

<#
.SYNOPSIS
Drucker-Migrationstool - Drucker mit Treibern und Anschluessen sichern und wiederherstellen
.DESCRIPTION
Exportiert und importiert Windows-Drucker inklusive TCP/IP-Anschluesse und Treiber.
Loest das Problem, dass die Windows-Druckerverwaltung Anschluesse nicht korrekt migriert.
Alles wird in eine einzige .pmb-Datei gepackt (ZIP-Format).
.NOTES
Muss als Administrator ausgefuehrt werden.
Kompatibel mit Windows 10/11 (PowerShell 5.1+)
#>
param(
[switch]$NoElevate
)
# ============================================================
# Auto-Elevation - startet sich selbst als Admin neu
# ============================================================
if (-not $NoElevate) {
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal(
[Security.Principal.WindowsIdentity]::GetCurrent()
)
if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
$scriptPath = if ($PSCommandPath) { $PSCommandPath } else { $MyInvocation.MyCommand.Path }
if ($scriptPath) {
Start-Process powershell.exe -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`"" -Verb RunAs
} else {
Write-Host "Bitte starten Sie das Skript als Administrator." -ForegroundColor Red
}
exit
}
}
# ============================================================
# Voraussetzungen pruefen
# ============================================================
if (-not (Get-Module -ListAvailable -Name PrintManagement -ErrorAction SilentlyContinue)) {
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.MessageBox]::Show(
"Das PrintManagement-Modul ist nicht verfuegbar.`nDieses Tool benoetigt Windows 10/11 Pro oder Enterprise.",
"Fehler",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Error
) | Out-Null
exit 1
}
# ============================================================
# Assemblies laden
# ============================================================
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[System.Windows.Forms.Application]::EnableVisualStyles()
# ============================================================
# Globale Variablen
# ============================================================
$script:LogBox = $null
$script:ProgressBar = $null
$script:StatusLabel = $null
# ============================================================
# Hilfsfunktionen
# ============================================================
function Write-Log {
param(
[string]$Message,
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "HH:mm:ss"
$logMessage = "[$timestamp] $Message"
if ($script:LogBox) {
$script:LogBox.AppendText("$logMessage`r`n")
$script:LogBox.SelectionStart = $script:LogBox.TextLength
$script:LogBox.ScrollToCaret()
[System.Windows.Forms.Application]::DoEvents()
}
}
function Update-Progress {
param(
[int]$Current,
[int]$Total,
[string]$Status
)
if ($script:ProgressBar -and $Total -gt 0) {
$percent = [math]::Min(100, [math]::Round(($Current / $Total) * 100))
$script:ProgressBar.Value = $percent
}
if ($script:StatusLabel) {
$script:StatusLabel.Text = $Status
}
[System.Windows.Forms.Application]::DoEvents()
}
# ============================================================
# Datensammlung - Anschlussdetails ermitteln
# ============================================================
function Get-PrinterPortDetails {
param([string]$PortName)
$portInfo = @{
Name = $PortName
Type = "Unknown"
}
# TCP/IP-Anschluss per WMI abfragen (liefert die meisten Details)
try {
$tcpPort = Get-CimInstance -ClassName Win32_TCPIPPrinterPort `
-Filter "Name='$($PortName -replace "'","''")'" -ErrorAction SilentlyContinue
if ($tcpPort) {
$portInfo.Type = "TCPIP"
$portInfo.HostAddress = $tcpPort.HostAddress
$portInfo.PortNumber = $tcpPort.PortNumber
$portInfo.Protocol = $tcpPort.Protocol # 1=RAW, 2=LPR
$portInfo.SNMPEnabled = $tcpPort.SNMPEnabled
$portInfo.SNMPCommunity = $tcpPort.SNMPCommunity
$portInfo.SNMPDevIndex = $tcpPort.SNMPDevIndex
$portInfo.Queue = $tcpPort.Queue
return $portInfo
}
} catch {}
# Fallback: Anschluss-Typ anhand des Namens erkennen
try {
$port = Get-PrinterPort -Name $PortName -ErrorAction SilentlyContinue
if ($port) {
$portInfo.Description = $port.Description
if ($PortName -match '^(LPT|COM)\d+:?$') {
$portInfo.Type = "Local"
}
elseif ($PortName -eq 'FILE:' -or $PortName -eq 'PORTPROMPT:') {
$portInfo.Type = "File"
}
elseif ($PortName -match '^USB') {
$portInfo.Type = "USB"
}
elseif ($PortName -match '^WSD') {
$portInfo.Type = "WSD"
}
elseif ($PortName -match '^TS\d') {
$portInfo.Type = "TerminalService"
}
elseif ($port.Description -match 'TCP' -or $PortName -match 'IP_') {
$portInfo.Type = "TCPIP"
if ($port.PrinterHostAddress) {
$portInfo.HostAddress = $port.PrinterHostAddress
$portInfo.PortNumber = if ($port.PortNumber) { $port.PortNumber } else { 9100 }
}
}
else {
$portInfo.Type = "Other"
}
}
} catch {}
return $portInfo
}
# ============================================================
# Datensammlung - Treiberdetails ermitteln
# ============================================================
function Get-PrinterDriverDetails {
param([string]$DriverName)
$driverInfo = @{
Name = $DriverName
InfPath = ""
InfFileName = ""
PackageDirectory = ""
PrinterEnvironment = ""
MajorVersion = 0
Manufacturer = ""
PrintProcessor = ""
Files = @()
}
try {
$driver = Get-PrinterDriver -Name $DriverName -ErrorAction SilentlyContinue
if ($driver) {
$driverInfo.InfPath = $driver.InfPath
$driverInfo.PrinterEnvironment = $driver.PrinterEnvironment
$driverInfo.MajorVersion = $driver.MajorVersion
$driverInfo.Manufacturer = $driver.Manufacturer
$driverInfo.PrintProcessor = $driver.PrintProcessor
# Paketverzeichnis aus INF-Pfad ableiten
# System-INFs wie delegwiz.inf ausfiltern - das sind keine echten Treiber-INFs
$systemInfs = @('delegwiz.inf', 'ntprint.inf', 'prnms001.inf', 'prnms002.inf')
if ($driver.InfPath -and (Test-Path $driver.InfPath)) {
$infName = Split-Path -Leaf $driver.InfPath
if ($systemInfs -notcontains $infName.ToLower()) {
$driverInfo.PackageDirectory = Split-Path -Parent $driver.InfPath
$driverInfo.InfFileName = $infName
}
}
# Einzelne Treiberdateien sammeln
$filePaths = @()
@('DriverPath', 'ConfigFile', 'DataFile', 'HelpFile') | ForEach-Object {
if ($driver.$_) { $filePaths += $driver.$_ }
}
if ($driver.DependentFiles) {
$filePaths += $driver.DependentFiles
}
$driverInfo.Files = @($filePaths | Select-Object -Unique | Where-Object { $_ })
}
} catch {
Write-Log " Warnung: Treiberdetails fuer '$DriverName' konnten nicht gelesen werden: $_" "WARN"
}
return $driverInfo
}
# ============================================================
# Datensammlung - Alle Drucker erfassen
# ============================================================
function Get-AllPrinterData {
$printers = @()
try {
$installedPrinters = Get-Printer -ErrorAction Stop
$defaultPrinterName = ""
try {
$defaultObj = Get-CimInstance -ClassName Win32_Printer -Filter "Default=True" -ErrorAction SilentlyContinue
if ($defaultObj) { $defaultPrinterName = $defaultObj.Name }
} catch {}
foreach ($printer in $installedPrinters) {
$portDetails = Get-PrinterPortDetails -PortName $printer.PortName
$driverDetails = Get-PrinterDriverDetails -DriverName $printer.DriverName
# Druckkonfiguration abfragen
$duplexMode = ""
$color = $null
try {
$cfg = Get-PrintConfiguration -PrinterName $printer.Name -ErrorAction SilentlyContinue
if ($cfg) {
$duplexMode = [string]$cfg.DuplexingMode
$color = $cfg.Color
}
} catch {}
$printerData = @{
Name = $printer.Name
DriverName = $printer.DriverName
PortName = $printer.PortName
Shared = $printer.Shared
ShareName = $printer.ShareName
Comment = $printer.Comment
Location = $printer.Location
PrintProcessor = $printer.PrintProcessor
DataType = $printer.Datatype
IsDefault = ($printer.Name -eq $defaultPrinterName)
DuplexingMode = $duplexMode
Color = $color
Port = $portDetails
Driver = $driverDetails
}
$printers += $printerData
}
} catch {
Write-Log "Fehler beim Lesen der Drucker: $_" "ERROR"
}
return $printers
}
# ============================================================
# EXPORT - Sicherung erstellen
# ============================================================
function Export-PrinterBackup {
param(
[array]$SelectedPrinters,
[string]$OutputPath
)
$tempDir = Join-Path $env:TEMP "PrinterMigrator_Export_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
$driversDir = Join-Path $tempDir "drivers"
try {
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
New-Item -ItemType Directory -Path $driversDir -Force | Out-Null
$totalSteps = $SelectedPrinters.Count + 1
$currentStep = 0
$backedUpDrivers = @{}
# Exportdaten vorbereiten (tiefe Kopie pro Drucker)
$exportPrinters = @()
foreach ($printer in $SelectedPrinters) {
$currentStep++
Update-Progress -Current $currentStep -Total $totalSteps `
-Status "Verarbeite: $($printer.Name)"
# Exportstruktur fuer diesen Drucker erstellen
$exportPrinter = @{
Name = $printer.Name
DriverName = $printer.DriverName
PortName = $printer.PortName
Shared = $printer.Shared
ShareName = $printer.ShareName
Comment = $printer.Comment
Location = $printer.Location
PrintProcessor = $printer.PrintProcessor
DataType = $printer.DataType
IsDefault = $printer.IsDefault
DuplexingMode = $printer.DuplexingMode
Color = $printer.Color
Port = $printer.Port
Driver = @{
Name = $printer.Driver.Name
InfFileName = $printer.Driver.InfFileName
PrinterEnvironment = $printer.Driver.PrinterEnvironment
MajorVersion = $printer.Driver.MajorVersion
Manufacturer = $printer.Driver.Manufacturer
PrintProcessor = $printer.Driver.PrintProcessor
BackupPackageDir = ""
BackupInfPath = ""
}
}
$driverName = $printer.DriverName
# Treiber nur einmal sichern (auch wenn mehrere Drucker ihn nutzen)
if (-not $backedUpDrivers.ContainsKey($driverName)) {
Write-Log " Treiber sichern: $driverName"
$safeDirName = $driverName -replace '[\\/:*?"<>|]', '_'
$driverDir = Join-Path $driversDir $safeDirName
New-Item -ItemType Directory -Path $driverDir -Force | Out-Null
$filesCopied = 0
# Ganzes Treiberpaket-Verzeichnis kopieren (bevorzugt)
$pkgDir = $printer.Driver.PackageDirectory
if ($pkgDir -and (Test-Path $pkgDir)) {
try {
$pkgDest = Join-Path $driverDir "package"
Copy-Item -Path $pkgDir -Destination $pkgDest -Recurse -Force -ErrorAction Stop
$filesCopied = (Get-ChildItem -Path $pkgDest -Recurse -File).Count
Write-Log " Treiberpaket kopiert ($filesCopied Dateien)"
$backedUpDrivers[$driverName] = @{
BackupPackageDir = "package"
BackupInfPath = if ($printer.Driver.InfFileName) {
"package\$($printer.Driver.InfFileName)"
} else { "" }
}
} catch {
Write-Log " Warnung: Treiberpaket konnte nicht kopiert werden: $_"
}
}
# Einzelne Treiberdateien als Fallback kopieren
if ($filesCopied -eq 0 -and $printer.Driver.Files -and $printer.Driver.Files.Count -gt 0) {
$filesDir = Join-Path $driverDir "files"
New-Item -ItemType Directory -Path $filesDir -Force | Out-Null
foreach ($file in $printer.Driver.Files) {
if ($file -and (Test-Path $file)) {
try {
Copy-Item -Path $file -Destination $filesDir -Force -ErrorAction Stop
$filesCopied++
} catch {
Write-Log " Warnung: $file konnte nicht kopiert werden"
}
}
}
if ($filesCopied -gt 0) {
Write-Log " $filesCopied Einzeldateien kopiert"
}
}
if ($filesCopied -eq 0) {
Write-Log " Hinweis: Keine Treiberdateien gesichert - Treiber muss ggf. manuell installiert werden"
}
if (-not $backedUpDrivers.ContainsKey($driverName)) {
$backedUpDrivers[$driverName] = @{
BackupPackageDir = ""
BackupInfPath = ""
}
}
}
# Backup-Pfade im Export setzen
$driverBackup = $backedUpDrivers[$driverName]
$exportPrinter.Driver.BackupPackageDir = $driverBackup.BackupPackageDir
$exportPrinter.Driver.BackupInfPath = $driverBackup.BackupInfPath
Write-Log " Drucker '$($printer.Name)' verarbeitet."
$exportPrinters += $exportPrinter
}
# JSON-Konfiguration schreiben
$exportData = @{
ExportDate = (Get-Date -Format "o")
ComputerName = $env:COMPUTERNAME
OSVersion = [System.Environment]::OSVersion.VersionString
ToolVersion = "1.0"
Printers = $exportPrinters
}
$jsonPath = Join-Path $tempDir "config.json"
$exportData | ConvertTo-Json -Depth 10 | Out-File -FilePath $jsonPath -Encoding UTF8
# ZIP erstellen
$currentStep++
Update-Progress -Current $currentStep -Total $totalSteps `
-Status "Sicherungsdatei erstellen..."
if (Test-Path $OutputPath) {
Remove-Item $OutputPath -Force
}
Compress-Archive -Path "$tempDir\*" -DestinationPath $OutputPath -Force
$fileSize = [math]::Round((Get-Item $OutputPath).Length / 1MB, 2)
Write-Log ""
Write-Log "=== Sicherung erfolgreich ==="
Write-Log "Datei: $OutputPath"
Write-Log "Groesse: $fileSize MB"
Write-Log "$($SelectedPrinters.Count) Drucker gesichert."
Update-Progress -Current $totalSteps -Total $totalSteps -Status "Fertig!"
return $true
} catch {
Write-Log "Fehler bei der Sicherung: $_" "ERROR"
return $false
} finally {
if (Test-Path $tempDir) {
Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
}
# ============================================================
# IMPORT - Sicherungsdatei laden
# ============================================================
function Import-PrinterBackup {
param([string]$BackupPath)
$tempDir = Join-Path $env:TEMP "PrinterMigrator_Import_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
try {
Expand-Archive -Path $BackupPath -DestinationPath $tempDir -Force
$jsonPath = Join-Path $tempDir "config.json"
if (-not (Test-Path $jsonPath)) {
Write-Log "Fehler: config.json nicht in der Sicherungsdatei gefunden!" "ERROR"
return $null
}
$importData = Get-Content -Path $jsonPath -Raw -Encoding UTF8 | ConvertFrom-Json
Write-Log "Sicherung geladen:"
Write-Log " Erstellt am: $($importData.ExportDate)"
Write-Log " Computer: $($importData.ComputerName)"
Write-Log " $($importData.Printers.Count) Drucker in der Sicherung"
return @{
Data = $importData
TempDir = $tempDir
}
} catch {
Write-Log "Fehler beim Lesen der Sicherung: $_" "ERROR"
if (Test-Path $tempDir) {
Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue
}
return $null
}
}
# ============================================================
# IMPORT - Anschluss wiederherstellen
# ============================================================
function Restore-PrinterPort {
param([PSCustomObject]$PortData)
$portName = $PortData.Name
# Pruefen ob Anschluss bereits existiert
$existing = Get-PrinterPort -Name $portName -ErrorAction SilentlyContinue
if ($existing) {
Write-Log " Anschluss '$portName' existiert bereits."
return $true
}
try {
switch ($PortData.Type) {
"TCPIP" {
$address = $PortData.HostAddress
$portNumber = if ($PortData.PortNumber) { [int]$PortData.PortNumber } else { 9100 }
if (-not $address) {
Write-Log " Fehler: Keine IP-Adresse fuer Anschluss '$portName'" "ERROR"
return $false
}
# LPR-Protokoll (Protocol=2) oder RAW (Protocol=1, Standard)
if ($PortData.Protocol -eq 2) {
$queue = if ($PortData.Queue) { $PortData.Queue } else { "lp" }
Add-PrinterPort -Name $portName `
-PrinterHostAddress $address `
-LprHostAddress $address `
-LprQueueName $queue `
-LprByteCounting:$true -ErrorAction Stop
Write-Log " LPR-Anschluss erstellt: $portName -> $address (Queue: $queue)"
}
else {
Add-PrinterPort -Name $portName `
-PrinterHostAddress $address `
-PortNumber $portNumber -ErrorAction Stop
Write-Log " TCP/IP-Anschluss erstellt: $portName -> ${address}:${portNumber}"
}
# SNMP konfigurieren falls aktiviert
if ($PortData.SNMPEnabled -eq $true) {
try {
$snmpCommunity = if ($PortData.SNMPCommunity) { $PortData.SNMPCommunity } else { "public" }
$snmpIndex = if ($PortData.SNMPDevIndex) { [int]$PortData.SNMPDevIndex } else { 1 }
$wmiPort = Get-CimInstance -ClassName Win32_TCPIPPrinterPort -Filter "Name='$($portName -replace "'","''")'"
if ($wmiPort) {
Set-CimInstance -InputObject $wmiPort -Property @{
SNMPEnabled = $true
SNMPCommunity = $snmpCommunity
SNMPDevIndex = $snmpIndex
}
Write-Log " SNMP aktiviert ($snmpCommunity)"
}
} catch {
Write-Log " Warnung: SNMP konnte nicht konfiguriert werden"
}
}
return $true
}
"Local" {
Write-Log " Lokaler Anschluss '$portName' (systemverwaltet)"
return $true
}
"File" {
Write-Log " Dateianschluss '$portName' (immer verfuegbar)"
return $true
}
"USB" {
Write-Log " USB-Anschluss '$portName' - wird beim Anschliessen des Geraets erstellt"
return $true
}
"WSD" {
Write-Log " WSD-Anschluss '$portName' - wird durch Netzwerkerkennung erstellt"
return $true
}
"TerminalService" {
Write-Log " TS-Anschluss '$portName' - wird durch Terminaldienste verwaltet"
return $true
}
default {
# Generischen Anschluss versuchen zu erstellen
try {
Add-PrinterPort -Name $portName -ErrorAction Stop
Write-Log " Anschluss erstellt: $portName"
return $true
} catch {
Write-Log " Warnung: Anschluss '$portName' konnte nicht erstellt werden: $_"
return $false
}
}
}
} catch {
Write-Log " Fehler beim Erstellen des Anschlusses '$portName': $_" "ERROR"
return $false
}
}
# ============================================================
# IMPORT - Treiber wiederherstellen
# ============================================================
function Restore-PrinterDriver {
param(
[PSCustomObject]$DriverData,
[string]$BackupTempDir
)
$driverName = $DriverData.Name
# Pruefen ob Treiber bereits installiert ist
$existing = Get-PrinterDriver -Name $driverName -ErrorAction SilentlyContinue
if ($existing) {
Write-Log " Treiber '$driverName' ist bereits installiert."
return $true
}
# Treiber-Backup-Verzeichnis finden
$safeDirName = $driverName -replace '[\\/:*?"<>|]', '_'
$driversBaseDir = Join-Path $BackupTempDir "drivers"
$driverBackupDir = Join-Path $driversBaseDir $safeDirName
if (-not (Test-Path -LiteralPath $driverBackupDir)) {
Write-Log " Fehler: Treiberdateien fuer '$driverName' nicht in der Sicherung!" "ERROR"
Write-Log " Gesucht in: $driverBackupDir"
Write-Log " -> Bitte installieren Sie den Treiber manuell."
return $false
}
# Methode 1: INF-basierte Installation (bevorzugt)
$infPath = $null
# Zuerst die gespeicherte INF-Datei aus dem Backup verwenden
if ($DriverData.BackupInfPath) {
$testInf = Join-Path $driverBackupDir $DriverData.BackupInfPath
if (Test-Path -LiteralPath $testInf) {
$infPath = $testInf
}
}
# INF-Datei im Backup suchen falls nicht gefunden
# System-INFs wie delegwiz.inf, ntprint.inf etc. ausfiltern
if (-not $infPath) {
$systemInfs = @('delegwiz.inf', 'ntprint.inf', 'prnms001.inf', 'prnms002.inf')
$infFiles = Get-ChildItem -LiteralPath $driverBackupDir -Filter "*.inf" -Recurse -ErrorAction SilentlyContinue |
Where-Object { $systemInfs -notcontains $_.Name.ToLower() }
if ($infFiles) {
$infPath = @($infFiles)[0].FullName
}
}
if ($infPath) {
try {
Write-Log " Treiber installieren via INF: $(Split-Path -Leaf $infPath)"
# Treiber zum DriverStore hinzufuegen
$pnpResult = & pnputil.exe /add-driver "$infPath" /install 2>&1
$pnpOutput = ($pnpResult | Out-String).Trim()
if ($pnpOutput) {
Write-Log " pnputil: $pnpOutput"
}
# Druckertreiber registrieren
Add-PrinterDriver -Name $driverName -InfPath $infPath -ErrorAction Stop
Write-Log " Treiber '$driverName' erfolgreich installiert."
return $true
} catch {
Write-Log " Warnung: INF-Installation fehlgeschlagen: $_"
# Pruefen ob pnputil den Treiber trotzdem installiert hat
$retryDriver = Get-PrinterDriver -Name $driverName -ErrorAction SilentlyContinue
if ($retryDriver) {
Write-Log " Treiber wurde dennoch gefunden - OK."
return $true
}
}
}
Write-Log " Fehler: Treiber '$driverName' konnte nicht installiert werden." "ERROR"
Write-Log " -> Bitte installieren Sie den Treiber manuell und fuehren Sie die Wiederherstellung erneut aus."
return $false
}
# ============================================================
# IMPORT - Einzelnen Drucker wiederherstellen
# ============================================================
function Restore-SinglePrinter {
param(
[PSCustomObject]$PrinterData,
[string]$BackupTempDir,
[bool]$Overwrite = $false
)
$printerName = $PrinterData.Name
Write-Log ""
Write-Log "--- Drucker: $printerName ---"
# Pruefen ob Drucker bereits existiert
$existing = Get-Printer -Name $printerName -ErrorAction SilentlyContinue
if ($existing) {
if ($Overwrite) {
Write-Log " Vorhandener Drucker wird entfernt..."
Remove-Printer -Name $printerName -ErrorAction SilentlyContinue
Start-Sleep -Milliseconds 500
} else {
Write-Log " Drucker existiert bereits - wird uebersprungen."
Write-Log " (Aktivieren Sie 'Vorhandene ueberschreiben' um zu ersetzen)"
return $true
}
}
# Schritt 1: Anschluss erstellen
Write-Log " [1/3] Anschluss erstellen..."
$portOk = Restore-PrinterPort -PortData $PrinterData.Port
# Pruefen ob Anschluss verfuegbar ist
$portExists = Get-PrinterPort -Name $PrinterData.PortName -ErrorAction SilentlyContinue
if (-not $portExists -and -not $portOk) {
Write-Log " ABBRUCH: Anschluss '$($PrinterData.PortName)' nicht verfuegbar!" "ERROR"
return $false
}
# Schritt 2: Treiber installieren
Write-Log " [2/3] Treiber installieren..."
$driverOk = Restore-PrinterDriver -DriverData $PrinterData.Driver -BackupTempDir $BackupTempDir
if (-not $driverOk) {
$driverExists = Get-PrinterDriver -Name $PrinterData.DriverName -ErrorAction SilentlyContinue
if (-not $driverExists) {
Write-Log " ABBRUCH: Treiber '$($PrinterData.DriverName)' nicht verfuegbar!" "ERROR"
return $false
}
}
# Schritt 3: Drucker erstellen
Write-Log " [3/3] Drucker erstellen..."
try {
$addParams = @{
Name = $printerName
DriverName = $PrinterData.DriverName
PortName = $PrinterData.PortName
}
if ($PrinterData.Comment) { $addParams.Comment = $PrinterData.Comment }
if ($PrinterData.Location) { $addParams.Location = $PrinterData.Location }
if ($PrinterData.Shared -eq $true) {
$addParams.Shared = $true
if ($PrinterData.ShareName) { $addParams.ShareName = $PrinterData.ShareName }
}
Add-Printer @addParams -ErrorAction Stop
Write-Log " Drucker '$printerName' erstellt."
# Standarddrucker setzen
if ($PrinterData.IsDefault -eq $true) {
try {
$escapedName = $printerName -replace "'","''"
$wmPrinter = Get-CimInstance -ClassName Win32_Printer -Filter "Name='$escapedName'"
if ($wmPrinter) {
Invoke-CimMethod -InputObject $wmPrinter -MethodName SetDefaultPrinter | Out-Null
Write-Log " Als Standarddrucker festgelegt."
}
} catch {
Write-Log " Warnung: Standarddrucker konnte nicht gesetzt werden"
}
}
# Druckkonfiguration setzen
try {
if ($PrinterData.DuplexingMode -and $PrinterData.DuplexingMode -ne '') {
Set-PrintConfiguration -PrinterName $printerName `
-DuplexingMode $PrinterData.DuplexingMode -ErrorAction SilentlyContinue
}
if ($PrinterData.Color -ne $null) {
Set-PrintConfiguration -PrinterName $printerName `
-Color $PrinterData.Color -ErrorAction SilentlyContinue
}
} catch {}
Write-Log " -> Erfolgreich!"
return $true
} catch {
Write-Log " Fehler beim Erstellen des Druckers: $_" "ERROR"
return $false
}
}
# ============================================================
# IMPORT - Ausgewaehlte Drucker wiederherstellen
# ============================================================
function Restore-SelectedPrinters {
param(
[array]$SelectedPrinters,
[string]$BackupTempDir,
[bool]$Overwrite = $false
)
$total = $SelectedPrinters.Count
$successCount = 0
$failCount = 0
for ($i = 0; $i -lt $total; $i++) {
$printer = $SelectedPrinters[$i]
Update-Progress -Current ($i + 1) -Total $total `
-Status "Wiederherstellen ($($i+1)/$total): $($printer.Name)"
$result = Restore-SinglePrinter -PrinterData $printer `
-BackupTempDir $BackupTempDir -Overwrite $Overwrite
if ($result) { $successCount++ } else { $failCount++ }
}
Update-Progress -Current $total -Total $total -Status "Fertig!"
Write-Log ""
Write-Log "========================================="
Write-Log " Wiederherstellung abgeschlossen"
Write-Log " Erfolgreich: $successCount / $total"
if ($failCount -gt 0) {
Write-Log " Fehlgeschlagen: $failCount"
}
Write-Log "========================================="
}
# ============================================================
# GUI - Hauptfenster
# ============================================================
function Show-MainForm {
$form = New-Object System.Windows.Forms.Form
$form.Text = "Drucker-Migrationstool"
$form.Size = New-Object System.Drawing.Size(780, 680)
$form.StartPosition = "CenterScreen"
$form.MinimumSize = New-Object System.Drawing.Size(650, 550)
$form.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$form.BackColor = [System.Drawing.Color]::FromArgb(245, 245, 245)
# Icon aus printui.exe laden
try {
$printUiPath = "$env:SystemRoot\System32\printui.exe"
if (Test-Path $printUiPath) {
$form.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($printUiPath)
}
} catch {}
# ============================================================
# OBERER BEREICH - Tabs mit Drucker-Listen
# ============================================================
$topPanel = New-Object System.Windows.Forms.Panel
$topPanel.Dock = [System.Windows.Forms.DockStyle]::Fill
$topPanel.Padding = New-Object System.Windows.Forms.Padding(8, 8, 8, 0)
$tabControl = New-Object System.Windows.Forms.TabControl
$tabControl.Dock = [System.Windows.Forms.DockStyle]::Fill
# ---- TAB: SICHERN ----
$tabExport = New-Object System.Windows.Forms.TabPage
$tabExport.Text = " Sichern "
$tabExport.Padding = New-Object System.Windows.Forms.Padding(12)
$tabExport.UseVisualStyleBackColor = $true
$pnlExport = New-Object System.Windows.Forms.Panel
$pnlExport.Dock = [System.Windows.Forms.DockStyle]::Fill
$lblExportTitle = New-Object System.Windows.Forms.Label
$lblExportTitle.Text = "Installierte Drucker - waehlen Sie aus, welche gesichert werden sollen:"
$lblExportTitle.Dock = [System.Windows.Forms.DockStyle]::Top
$lblExportTitle.Height = 25
$lblExportTitle.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$lstExport = New-Object System.Windows.Forms.CheckedListBox
$lstExport.Dock = [System.Windows.Forms.DockStyle]::Fill
$lstExport.CheckOnClick = $true
$lstExport.BorderStyle = "FixedSingle"
$lstExport.IntegralHeight = $false
$pnlExportButtons = New-Object System.Windows.Forms.Panel
$pnlExportButtons.Dock = [System.Windows.Forms.DockStyle]::Bottom
$pnlExportButtons.Height = 50
$pnlExportButtons.Padding = New-Object System.Windows.Forms.Padding(0, 8, 0, 0)
$btnExportAll = New-Object System.Windows.Forms.Button
$btnExportAll.Text = "Alle auswaehlen"
$btnExportAll.Location = New-Object System.Drawing.Point(0, 10)
$btnExportAll.Size = New-Object System.Drawing.Size(130, 30)
$btnExportAll.FlatStyle = "Flat"
$btnExportNone = New-Object System.Windows.Forms.Button
$btnExportNone.Text = "Keine auswaehlen"
$btnExportNone.Location = New-Object System.Drawing.Point(140, 10)
$btnExportNone.Size = New-Object System.Drawing.Size(130, 30)
$btnExportNone.FlatStyle = "Flat"
$btnExport = New-Object System.Windows.Forms.Button
$btnExport.Text = " Sicherung erstellen... "
$btnExport.Location = New-Object System.Drawing.Point(310, 6)
$btnExport.Size = New-Object System.Drawing.Size(210, 36)
$btnExport.FlatStyle = "Flat"
$btnExport.BackColor = [System.Drawing.Color]::FromArgb(0, 120, 215)
$btnExport.ForeColor = [System.Drawing.Color]::White
$btnExport.Font = New-Object System.Drawing.Font("Segoe UI", 9.5, [System.Drawing.FontStyle]::Bold)
$btnExport.Cursor = [System.Windows.Forms.Cursors]::Hand
$pnlExportButtons.Controls.AddRange(@($btnExportAll, $btnExportNone, $btnExport))
$pnlExport.Controls.Add($lstExport)
$pnlExport.Controls.Add($pnlExportButtons)
$pnlExport.Controls.Add($lblExportTitle)
$tabExport.Controls.Add($pnlExport)
# ---- TAB: WIEDERHERSTELLEN ----
$tabImport = New-Object System.Windows.Forms.TabPage
$tabImport.Text = " Wiederherstellen "
$tabImport.Padding = New-Object System.Windows.Forms.Padding(12)
$tabImport.UseVisualStyleBackColor = $true
$pnlImport = New-Object System.Windows.Forms.Panel
$pnlImport.Dock = [System.Windows.Forms.DockStyle]::Fill
# Dateiauswahl-Zeile
$pnlImportFile = New-Object System.Windows.Forms.Panel
$pnlImportFile.Dock = [System.Windows.Forms.DockStyle]::Top
$pnlImportFile.Height = 62
$lblImportFile = New-Object System.Windows.Forms.Label
$lblImportFile.Text = "Sicherungsdatei (.zip) auswaehlen:"
$lblImportFile.Location = New-Object System.Drawing.Point(0, 0)
$lblImportFile.AutoSize = $true
$lblImportFile.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$txtImportPath = New-Object System.Windows.Forms.TextBox
$txtImportPath.Location = New-Object System.Drawing.Point(0, 22)
$txtImportPath.Size = New-Object System.Drawing.Size(550, 25)
$txtImportPath.Anchor = "Top,Left"
$txtImportPath.ReadOnly = $true
$txtImportPath.BackColor = [System.Drawing.Color]::White
$btnBrowse = New-Object System.Windows.Forms.Button
$btnBrowse.Text = "Durchsuchen..."
$btnBrowse.Location = New-Object System.Drawing.Point(558, 20)
$btnBrowse.Size = New-Object System.Drawing.Size(120, 28)
$btnBrowse.Anchor = "Top,Left"
$btnBrowse.FlatStyle = "Flat"
$pnlImportFile.Controls.AddRange(@($lblImportFile, $txtImportPath, $btnBrowse))
$btnBrowse.BringToFront()
# Druckerliste
$lblImportList = New-Object System.Windows.Forms.Label
$lblImportList.Text = "Drucker in der Sicherung:"
$lblImportList.Dock = [System.Windows.Forms.DockStyle]::Top
$lblImportList.Height = 22
$lstImport = New-Object System.Windows.Forms.CheckedListBox
$lstImport.Dock = [System.Windows.Forms.DockStyle]::Fill
$lstImport.CheckOnClick = $true
$lstImport.BorderStyle = "FixedSingle"
$lstImport.IntegralHeight = $false
# Buttons unten
$pnlImportButtons = New-Object System.Windows.Forms.Panel
$pnlImportButtons.Dock = [System.Windows.Forms.DockStyle]::Bottom
$pnlImportButtons.Height = 50
$pnlImportButtons.Padding = New-Object System.Windows.Forms.Padding(0, 8, 0, 0)
$btnImportAll = New-Object System.Windows.Forms.Button
$btnImportAll.Text = "Alle auswaehlen"
$btnImportAll.Location = New-Object System.Drawing.Point(0, 10)
$btnImportAll.Size = New-Object System.Drawing.Size(130, 30)
$btnImportAll.FlatStyle = "Flat"
$btnImportNone = New-Object System.Windows.Forms.Button
$btnImportNone.Text = "Keine auswaehlen"
$btnImportNone.Location = New-Object System.Drawing.Point(140, 10)
$btnImportNone.Size = New-Object System.Drawing.Size(130, 30)
$btnImportNone.FlatStyle = "Flat"
$btnImport = New-Object System.Windows.Forms.Button
$btnImport.Text = " Wiederherstellen... "
$btnImport.Location = New-Object System.Drawing.Point(290, 6)
$btnImport.Size = New-Object System.Drawing.Size(200, 36)
$btnImport.Anchor = "Top,Left"
$btnImport.FlatStyle = "Flat"
$btnImport.BackColor = [System.Drawing.Color]::FromArgb(16, 124, 16)
$btnImport.ForeColor = [System.Drawing.Color]::White
$btnImport.Font = New-Object System.Drawing.Font("Segoe UI", 9.5, [System.Drawing.FontStyle]::Bold)
$btnImport.Cursor = [System.Windows.Forms.Cursors]::Hand
$chkOverwrite = New-Object System.Windows.Forms.CheckBox
$chkOverwrite.Text = "Vorhandene ueberschreiben"
$chkOverwrite.Location = New-Object System.Drawing.Point(500, 14)
$chkOverwrite.AutoSize = $true
$pnlImportButtons.Controls.AddRange(@($btnImportAll, $btnImportNone, $btnImport, $chkOverwrite))
$pnlImport.Controls.Add($lstImport)
$pnlImport.Controls.Add($lblImportList)
$pnlImport.Controls.Add($pnlImportButtons)
$pnlImport.Controls.Add($pnlImportFile)
$tabImport.Controls.Add($pnlImport)
# ---- TAB: INFO ----
$tabInfo = New-Object System.Windows.Forms.TabPage
$tabInfo.Text = " Info "
$tabInfo.Padding = New-Object System.Windows.Forms.Padding(20)
$tabInfo.UseVisualStyleBackColor = $true
$pnlInfo = New-Object System.Windows.Forms.Panel
$pnlInfo.Dock = [System.Windows.Forms.DockStyle]::Fill
$lblInfoText = New-Object System.Windows.Forms.Label
$lblInfoText.Dock = [System.Windows.Forms.DockStyle]::Top
$lblInfoText.AutoSize = $false
$lblInfoText.Height = 180
$lblInfoText.Font = New-Object System.Drawing.Font("Segoe UI", 10)
$lblInfoText.Text = @"
Drucker-Migrationstool v1.0
Exportiert und importiert Windows-Drucker inklusive
TCP/IP-Anschluesse und Treiber in eine einzelne ZIP-Datei.
HackerSoft - Hacker-Net Telekommunikation
Am Wunderburgpark 5b
26135 Oldenburg
"@
$lnkWeb = New-Object System.Windows.Forms.LinkLabel
$lnkWeb.Text = "www.hacker-net.de"
$lnkWeb.Dock = [System.Windows.Forms.DockStyle]::Top
$lnkWeb.Height = 25
$lnkWeb.Font = New-Object System.Drawing.Font("Segoe UI", 10)
$lnkWeb.Add_LinkClicked({ Start-Process "https://www.hacker-net.de" })
$lnkRepo = New-Object System.Windows.Forms.LinkLabel
$lnkRepo.Text = "Repository: git.hacker-net.de/Hacker-Software/windows-printer-migrator"
$lnkRepo.Dock = [System.Windows.Forms.DockStyle]::Top
$lnkRepo.Height = 25
$lnkRepo.Font = New-Object System.Drawing.Font("Segoe UI", 10)
$lnkRepo.Add_LinkClicked({ Start-Process "https://git.hacker-net.de/Hacker-Software/windows-printer-migrator" })
$pnlInfo.Controls.Add($lnkRepo)
$pnlInfo.Controls.Add($lnkWeb)
$pnlInfo.Controls.Add($lblInfoText)
$tabInfo.Controls.Add($pnlInfo)
# Tabs zum TabControl hinzufuegen
$tabControl.TabPages.Add($tabExport)
$tabControl.TabPages.Add($tabImport)
$tabControl.TabPages.Add($tabInfo)
$topPanel.Controls.Add($tabControl)
# ============================================================
# UNTERER BEREICH - Protokoll & Fortschritt
# ============================================================
$bottomPanel = New-Object System.Windows.Forms.Panel
$bottomPanel.Dock = [System.Windows.Forms.DockStyle]::Bottom
$bottomPanel.Height = 200
$bottomPanel.Padding = New-Object System.Windows.Forms.Padding(8, 4, 8, 8)
$lblLog = New-Object System.Windows.Forms.Label
$lblLog.Text = "Protokoll:"
$lblLog.Dock = [System.Windows.Forms.DockStyle]::Top
$lblLog.Height = 20
$lblLog.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$logBox = New-Object System.Windows.Forms.TextBox
$logBox.Multiline = $true
$logBox.ReadOnly = $true
$logBox.ScrollBars = "Vertical"
$logBox.Dock = [System.Windows.Forms.DockStyle]::Fill
$logBox.Font = New-Object System.Drawing.Font("Consolas", 8.5)
$logBox.BackColor = [System.Drawing.Color]::FromArgb(30, 30, 30)
$logBox.ForeColor = [System.Drawing.Color]::FromArgb(220, 220, 220)
$logBox.WordWrap = $false
$script:LogBox = $logBox
$statusPanel = New-Object System.Windows.Forms.Panel
$statusPanel.Dock = [System.Windows.Forms.DockStyle]::Bottom
$statusPanel.Height = 42
$statusLabel = New-Object System.Windows.Forms.Label
$statusLabel.Text = "Bereit"
$statusLabel.Dock = [System.Windows.Forms.DockStyle]::Top
$statusLabel.Height = 18
$script:StatusLabel = $statusLabel
$progressBar = New-Object System.Windows.Forms.ProgressBar
$progressBar.Dock = [System.Windows.Forms.DockStyle]::Bottom
$progressBar.Height = 22
$progressBar.Style = "Continuous"
$script:ProgressBar = $progressBar
$statusPanel.Controls.Add($progressBar)
$statusPanel.Controls.Add($statusLabel)
$bottomPanel.Controls.Add($logBox)
$bottomPanel.Controls.Add($lblLog)
$bottomPanel.Controls.Add($statusPanel)
# Splitter zwischen oben und unten
$splitter = New-Object System.Windows.Forms.Splitter
$splitter.Dock = [System.Windows.Forms.DockStyle]::Bottom
$splitter.Height = 5
$splitter.BackColor = [System.Drawing.Color]::FromArgb(200, 200, 200)
$form.Controls.Add($topPanel)
$form.Controls.Add($splitter)
$form.Controls.Add($bottomPanel)
# ============================================================
# Datenhaltung
# ============================================================
$script:AllPrinterData = @()
$script:ImportData = $null
$script:ImportTempDir = ""
# ============================================================
# EVENT HANDLER
# ============================================================
# --- Formular wird angezeigt: Drucker laden ---
$form.Add_Shown({
Write-Log "Drucker werden geladen..."
$script:AllPrinterData = Get-AllPrinterData
$lstExport.Items.Clear()
foreach ($p in $script:AllPrinterData) {
$portInfo = switch ($p.Port.Type) {
"TCPIP" { "$($p.Port.HostAddress)" + $(if ($p.Port.PortNumber -and $p.Port.PortNumber -ne 9100) { ":$($p.Port.PortNumber)" } else { "" }) }
default { $p.PortName }
}
$default = if ($p.IsDefault) { " *" } else { "" }
$display = "$($p.Name) | $portInfo | $($p.DriverName)$default"
$lstExport.Items.Add($display) | Out-Null
}
Write-Log "$($script:AllPrinterData.Count) Drucker gefunden."
if ($script:AllPrinterData.Count -gt 0) {
Write-Log "(* = Standarddrucker)"
}
Write-Log ""
})
# --- Alle/Keine auswaehlen: Export ---
$btnExportAll.Add_Click({
for ($i = 0; $i -lt $lstExport.Items.Count; $i++) {
$lstExport.SetItemChecked($i, $true)
}
})
$btnExportNone.Add_Click({
for ($i = 0; $i -lt $lstExport.Items.Count; $i++) {
$lstExport.SetItemChecked($i, $false)
}
})
# --- SICHERUNG ERSTELLEN ---
$btnExport.Add_Click({
$checkedIndices = @($lstExport.CheckedIndices)
if ($checkedIndices.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show(
"Bitte waehlen Sie mindestens einen Drucker aus.",
"Keine Auswahl",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Warning
) | Out-Null
return
}
$saveDialog = New-Object System.Windows.Forms.SaveFileDialog
$saveDialog.Filter = "Drucker-Sicherung (*.zip)|*.zip|Alle Dateien (*.*)|*.*"
$saveDialog.DefaultExt = "zip"
$saveDialog.FileName = "Drucker_$($env:COMPUTERNAME)_$(Get-Date -Format 'yyyy-MM-dd')"
$saveDialog.Title = "Sicherungsdatei speichern"
if ($saveDialog.ShowDialog($form) -eq [System.Windows.Forms.DialogResult]::OK) {
$selectedPrinters = @()
foreach ($idx in $checkedIndices) {
$selectedPrinters += $script:AllPrinterData[$idx]
}
$script:ProgressBar.Value = 0
Write-Log "=== SICHERUNG STARTEN ==="
Write-Log "Ausgewaehlt: $($selectedPrinters.Count) Drucker"
Write-Log ""
$btnExport.Enabled = $false
$btnExportAll.Enabled = $false
$btnExportNone.Enabled = $false
$result = Export-PrinterBackup -SelectedPrinters $selectedPrinters `
-OutputPath $saveDialog.FileName
$btnExport.Enabled = $true
$btnExportAll.Enabled = $true
$btnExportNone.Enabled = $true
if ($result) {
[System.Windows.Forms.MessageBox]::Show(
"Sicherung erfolgreich erstellt!`n`n$($saveDialog.FileName)`n`nKopieren Sie diese Datei auf den Zielrechner und verwenden Sie dort den Tab 'Wiederherstellen'.",
"Sicherung erfolgreich",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Information
) | Out-Null
} else {
[System.Windows.Forms.MessageBox]::Show(
"Bei der Sicherung sind Fehler aufgetreten.`nDetails siehe Protokoll.",
"Fehler",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Error
) | Out-Null
}
}
})
# --- DATEI DURCHSUCHEN ---
$btnBrowse.Add_Click({
$openDialog = New-Object System.Windows.Forms.OpenFileDialog
$openDialog.Filter = "Drucker-Sicherung (*.zip)|*.zip|Alle Dateien (*.*)|*.*"
$openDialog.Title = "Sicherungsdatei oeffnen"
if ($openDialog.ShowDialog($form) -eq [System.Windows.Forms.DialogResult]::OK) {
$txtImportPath.Text = $openDialog.FileName
# Vorherigen Import aufraeumen
if ($script:ImportTempDir -and (Test-Path $script:ImportTempDir)) {
Remove-Item $script:ImportTempDir -Recurse -Force -ErrorAction SilentlyContinue
}
Write-Log ""
Write-Log "=== SICHERUNG LADEN ==="
$importResult = Import-PrinterBackup -BackupPath $openDialog.FileName
$lstImport.Items.Clear()
if ($importResult) {
$script:ImportData = $importResult.Data
$script:ImportTempDir = $importResult.TempDir
foreach ($p in $script:ImportData.Printers) {
$portInfo = switch ($p.Port.Type) {
"TCPIP" { "$($p.Port.HostAddress)" + $(if ($p.Port.PortNumber -and $p.Port.PortNumber -ne 9100) { ":$($p.Port.PortNumber)" } else { "" }) }
default { $p.PortName }
}
$default = if ($p.IsDefault) { " *" } else { "" }
$exists = if (Get-Printer -Name $p.Name -ErrorAction SilentlyContinue) { " [vorhanden]" } else { "" }
$display = "$($p.Name) | $portInfo | $($p.DriverName)$default$exists"
$lstImport.Items.Add($display) | Out-Null
}
Write-Log ""
}
}
})
# --- Alle/Keine auswaehlen: Import ---
$btnImportAll.Add_Click({
for ($i = 0; $i -lt $lstImport.Items.Count; $i++) {
$lstImport.SetItemChecked($i, $true)
}
})
$btnImportNone.Add_Click({
for ($i = 0; $i -lt $lstImport.Items.Count; $i++) {
$lstImport.SetItemChecked($i, $false)
}
})
# --- WIEDERHERSTELLEN ---
$btnImport.Add_Click({
$checkedIndices = @($lstImport.CheckedIndices)
if ($checkedIndices.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show(
"Bitte waehlen Sie mindestens einen Drucker aus.",
"Keine Auswahl",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Warning
) | Out-Null
return
}
if (-not $script:ImportData) {
[System.Windows.Forms.MessageBox]::Show(
"Bitte laden Sie zuerst eine Sicherungsdatei.",
"Keine Sicherung geladen",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Warning
) | Out-Null
return
}
$confirmResult = [System.Windows.Forms.MessageBox]::Show(
"Moechten Sie $($checkedIndices.Count) Drucker wiederherstellen?`n`nDabei werden Anschluesse, Treiber und Drucker erstellt.",
"Wiederherstellung bestaetigen",
[System.Windows.Forms.MessageBoxButtons]::YesNo,
[System.Windows.Forms.MessageBoxIcon]::Question
)
if ($confirmResult -eq [System.Windows.Forms.DialogResult]::Yes) {
$selectedPrinters = @()
foreach ($idx in $checkedIndices) {
$selectedPrinters += $script:ImportData.Printers[$idx]
}
$script:ProgressBar.Value = 0
Write-Log ""
Write-Log "=== WIEDERHERSTELLUNG STARTEN ==="
Write-Log "Ausgewaehlt: $($selectedPrinters.Count) Drucker"
$btnImport.Enabled = $false
$btnImportAll.Enabled = $false
$btnImportNone.Enabled = $false
$btnBrowse.Enabled = $false
Restore-SelectedPrinters -SelectedPrinters $selectedPrinters `
-BackupTempDir $script:ImportTempDir -Overwrite $chkOverwrite.Checked
$btnImport.Enabled = $true
$btnImportAll.Enabled = $true
$btnImportNone.Enabled = $true
$btnBrowse.Enabled = $true
[System.Windows.Forms.MessageBox]::Show(
"Wiederherstellung abgeschlossen!`nDetails siehe Protokoll.",
"Fertig",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Information
) | Out-Null
}
})
# --- Aufraeumen beim Schliessen ---
$form.Add_FormClosing({
if ($script:ImportTempDir -and (Test-Path $script:ImportTempDir)) {
Remove-Item $script:ImportTempDir -Recurse -Force -ErrorAction SilentlyContinue
}
})
# ============================================================
# FORMULAR ANZEIGEN
# ============================================================
[void]$form.ShowDialog()
$form.Dispose()
}
# ============================================================
# PROGRAMMSTART
# ============================================================
Show-MainForm