<# .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) { Write-Log " Treiber installieren via INF: $(Split-Path -Leaf $infPath)" # Schritt 1: Treiberpaket zum DriverStore hinzufuegen via pnputil $publishedInfPath = $null try { $pnpResult = & pnputil.exe /add-driver "$infPath" /install 2>&1 $pnpOutput = ($pnpResult | Out-String).Trim() Write-Log " pnputil: $pnpOutput" # Veroeffentlichten INF-Namen aus pnputil-Ausgabe extrahieren (z.B. oem60.inf) if ($pnpOutput -match '(oem\d+\.inf)') { $publishedInf = $matches[1] $publishedInfPath = Join-Path "$env:SystemRoot\INF" $publishedInf Write-Log " Veroeffentlichte INF: $publishedInfPath" } } catch { Write-Log " Warnung: pnputil fehlgeschlagen: $_" } # Schritt 2: Druckertreiber registrieren - mehrere Methoden versuchen $driverAdded = $false # Methode A: Mit veroeffentlichter INF aus dem DriverStore if (-not $driverAdded -and $publishedInfPath -and (Test-Path -LiteralPath $publishedInfPath)) { try { Add-PrinterDriver -Name $driverName -InfPath $publishedInfPath -ErrorAction Stop Write-Log " Treiber '$driverName' erfolgreich installiert (via DriverStore)." $driverAdded = $true } catch { Write-Log " Methode A (DriverStore-INF) fehlgeschlagen: $_" } } # Methode B: Mit original Backup-INF if (-not $driverAdded) { try { Add-PrinterDriver -Name $driverName -InfPath $infPath -ErrorAction Stop Write-Log " Treiber '$driverName' erfolgreich installiert (via Backup-INF)." $driverAdded = $true } catch { Write-Log " Methode B (Backup-INF) fehlgeschlagen: $_" } } # Methode C: printui.dll verwenden (robuster bei OEM-Treibern) if (-not $driverAdded) { $tryInf = if ($publishedInfPath -and (Test-Path -LiteralPath $publishedInfPath)) { $publishedInfPath } else { $infPath } try { Write-Log " Versuche printui.dll..." $printUiArgs = "printui.dll,PrintUIEntry /ia /m `"$driverName`" /f `"$tryInf`"" Start-Process rundll32.exe -ArgumentList $printUiArgs -Wait -NoNewWindow -ErrorAction Stop Start-Sleep -Milliseconds 1000 $check = Get-PrinterDriver -Name $driverName -ErrorAction SilentlyContinue if ($check) { Write-Log " Treiber '$driverName' erfolgreich installiert (via printui)." $driverAdded = $true } else { Write-Log " Methode C (printui) fehlgeschlagen." } } catch { Write-Log " Methode C (printui) fehlgeschlagen: $_" } } # Letzte Pruefung: Vielleicht wurde der Treiber doch registriert if (-not $driverAdded) { $finalCheck = Get-PrinterDriver -Name $driverName -ErrorAction SilentlyContinue if ($finalCheck) { Write-Log " Treiber '$driverName' ist jetzt verfuegbar." $driverAdded = $true } } if ($driverAdded) { 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