diff --git a/plugins/printers/client/Set-ShopdbPrinters.ps1 b/plugins/printers/client/Set-ShopdbPrinters.ps1 index d12a854..3fc34ee 100644 --- a/plugins/printers/client/Set-ShopdbPrinters.ps1 +++ b/plugins/printers/client/Set-ShopdbPrinters.ps1 @@ -93,6 +93,61 @@ if ($wanted.Count -eq 0) { } Log "assigned: $($wanted.Count) printer(s)" +function Ensure-Port([string]$address) { + $portname = 'IP_' + $address + if (-not (Get-PrinterPort -Name $portname -ErrorAction SilentlyContinue)) { + Add-PrinterPort -Name $portname -PrinterHostAddress $address -ErrorAction Stop + Log "port: $portname" + } + return $portname +} + +function Repair-Queue($queue, [string]$address, [string]$drivername) { + $name = $queue.Name + + # The address ShopDB holds is the truth about where the printer IS. A queue + # left pointing at the old address prints into the void, and looks fine. + if ($address) { + $wantedport = 'IP_' + $address + if ($queue.PortName -ne $wantedport) { + if ($WhatIfOnly) { + Log "WOULD repoint $name : $($queue.PortName) -> $wantedport" + } else { + try { + $portname = Ensure-Port $address + Set-Printer -Name $name -PortName $portname -ErrorAction Stop + Log "repointed $name : $($queue.PortName) -> $portname" + } catch { + Log "ERROR repointing ${name}: $($_.Exception.Message)" + } + } + } + } + + # A queue built on a driver the site has moved off keeps using it forever. + # Only corrected when the wanted driver is actually staged - swapping a queue + # onto a driver that is not installed would break a working printer. + if ($drivername -and $queue.DriverName -ne $drivername) { + if (-not (Get-PrinterDriver -Name $drivername -ErrorAction SilentlyContinue)) { + Log "SKIP driver fix for $name : '$drivername' is not staged" + } elseif ($WhatIfOnly) { + Log "WOULD re-driver $name : $($queue.DriverName) -> $drivername" + } else { + try { + Set-Printer -Name $name -DriverName $drivername -ErrorAction Stop + Log "re-drivered $name : $($queue.DriverName) -> $drivername" + } catch { + Log "ERROR re-drivering ${name}: $($_.Exception.Message)" + } + } + } + + if ($queue.PortName -eq ('IP_' + $address) -and + ($drivername -eq '' -or $queue.DriverName -eq $drivername)) { + Log "present: $name" + } +} + $existing = @{} foreach ($queue in (Get-Printer -ErrorAction SilentlyContinue)) { $existing[$queue.Name] = $queue @@ -104,19 +159,28 @@ foreach ($printer in $wanted) { if (-not $name) { continue } if ($printer.printerid -eq $defaultid) { $defaultname = $name } + $address = $printer.hostname + if (-not $address) { $address = $printer.ipaddress } + $drivername = $printer.drivername + if ($existing.ContainsKey($name)) { - Log "present: $name" + # A queue with the right NAME can still be wrong: pointing at a printer + # that has moved, or built on a driver that has since been replaced. + # Absence used to be the only thing fixed, so a bay with a stale queue + # looked converged and printed to the wrong device. + # + # Corrected IN PLACE with Set-Printer, never removed and recreated: the + # queue keeps its name, its sharing, its permissions, and whoever has it + # as their default keeps it. + Repair-Queue $existing[$name] $address $drivername continue } - $address = $printer.hostname - if (-not $address) { $address = $printer.ipaddress } if (-not $address) { Log "SKIP $name : no hostname or IP to point a port at" continue } - $drivername = $printer.drivername if (-not $drivername) { Log "SKIP $name : ShopDB has no driver name for it" continue @@ -132,12 +196,8 @@ foreach ($printer in $wanted) { continue } - $portname = 'IP_' + $address try { - if (-not (Get-PrinterPort -Name $portname -ErrorAction SilentlyContinue)) { - Add-PrinterPort -Name $portname -PrinterHostAddress $address -ErrorAction Stop - Log "port: $portname" - } + $portname = Ensure-Port $address Add-Printer -Name $name -DriverName $drivername -PortName $portname -ErrorAction Stop Log "created: $name -> $address ($drivername)" } catch {