Correct a drifted print queue instead of leaving it wrong

A queue was matched by NAME alone, so a bay whose printer had moved, or whose
queue was built on a driver the site has since replaced, looked converged and
printed to the wrong device. Absence was fixed; drift was not.

Set-ShopdbPrinters.ps1 now repoints a queue whose port does not match the
address ShopDB holds, and swaps a queue built on the wrong driver. Both are
things ShopDB is authoritative about: where the printer IS, and what drives it.

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 - which is what makes this safe to run every cycle on a live floor. There is
still no removal code path in this script at all.

Two guards, because a repair that breaks a working printer is worse than drift:
the driver is only swapped when the wanted one is actually staged, and
-WhatIfOnly reports both kinds of correction without making either.

Verified on Windows against a queue that had the right name, the wrong port, the
wrong driver AND was the logged-on user's default: both fields were corrected and
the queue was still the default afterwards. The earlier no-op guarantees were
re-run and still hold - nothing assigned changes nothing, and an assignment with
no default leaves the user's own default alone.
This commit is contained in:
cproudlock
2026-08-19 13:07:51 -04:00
parent e2c45d33bc
commit 1a5a1cd43d

View File

@@ -93,6 +93,61 @@ if ($wanted.Count -eq 0) {
} }
Log "assigned: $($wanted.Count) printer(s)" 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 = @{} $existing = @{}
foreach ($queue in (Get-Printer -ErrorAction SilentlyContinue)) { foreach ($queue in (Get-Printer -ErrorAction SilentlyContinue)) {
$existing[$queue.Name] = $queue $existing[$queue.Name] = $queue
@@ -104,19 +159,28 @@ foreach ($printer in $wanted) {
if (-not $name) { continue } if (-not $name) { continue }
if ($printer.printerid -eq $defaultid) { $defaultname = $name } if ($printer.printerid -eq $defaultid) { $defaultname = $name }
$address = $printer.hostname
if (-not $address) { $address = $printer.ipaddress }
$drivername = $printer.drivername
if ($existing.ContainsKey($name)) { 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 continue
} }
$address = $printer.hostname
if (-not $address) { $address = $printer.ipaddress }
if (-not $address) { if (-not $address) {
Log "SKIP $name : no hostname or IP to point a port at" Log "SKIP $name : no hostname or IP to point a port at"
continue continue
} }
$drivername = $printer.drivername
if (-not $drivername) { if (-not $drivername) {
Log "SKIP $name : ShopDB has no driver name for it" Log "SKIP $name : ShopDB has no driver name for it"
continue continue
@@ -132,12 +196,8 @@ foreach ($printer in $wanted) {
continue continue
} }
$portname = 'IP_' + $address
try { try {
if (-not (Get-PrinterPort -Name $portname -ErrorAction SilentlyContinue)) { $portname = Ensure-Port $address
Add-PrinterPort -Name $portname -PrinterHostAddress $address -ErrorAction Stop
Log "port: $portname"
}
Add-Printer -Name $name -DriverName $drivername -PortName $portname -ErrorAction Stop Add-Printer -Name $name -DriverName $drivername -PortName $portname -ErrorAction Stop
Log "created: $name -> $address ($drivername)" Log "created: $name -> $address ($drivername)"
} catch { } catch {