1320 lines
52 KiB
PowerShell
1320 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
|
|
if ($driver.InfPath -and (Test-Path $driver.InfPath)) {
|
|
$driverInfo.PackageDirectory = Split-Path -Parent $driver.InfPath
|
|
$driverInfo.InfFileName = Split-Path -Leaf $driver.InfPath
|
|
}
|
|
|
|
# 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 '[\\/:*?"<>|]', '_'
|
|
$driverBackupDir = Join-Path $BackupTempDir "drivers" $safeDirName
|
|
|
|
if (-not (Test-Path $driverBackupDir)) {
|
|
Write-Log " Fehler: Treiberdateien fuer '$driverName' nicht in der Sicherung!" "ERROR"
|
|
Write-Log " -> Bitte installieren Sie den Treiber manuell."
|
|
return $false
|
|
}
|
|
|
|
# Methode 1: INF-basierte Installation (bevorzugt)
|
|
$infPath = $null
|
|
|
|
if ($DriverData.BackupInfPath) {
|
|
$testInf = Join-Path $driverBackupDir $DriverData.BackupInfPath
|
|
if (Test-Path $testInf) {
|
|
$infPath = $testInf
|
|
}
|
|
}
|
|
|
|
# INF-Datei im Backup suchen falls nicht gefunden
|
|
if (-not $infPath) {
|
|
$infFiles = Get-ChildItem -Path $driverBackupDir -Filter "*.inf" -Recurse -ErrorAction SilentlyContinue
|
|
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
|