From 8ba86ba56031f7050a1b24364a37f88eeee0dfdc Mon Sep 17 00:00:00 2001 From: cproudlock Date: Tue, 25 Aug 2026 14:58:41 -0400 Subject: [PATCH] Write through the mapped drive, record the UNC The snapshot path stored against a marker read "W:\backup\partmarker\...". That mapping exists only inside the SYSTEM logon session, only while the GE-Enforce cycle is running, and only on that one bay - so the path recorded in ShopDB resolved to nothing for the person most likely to need it. Writing still goes through the drive letter, deliberately: that is the connection GE-Enforce authenticated, and reaching the same server by another name costs a second authentication or fails outright with error 1219. Only the recorded path changes. Resolving a mapped drive to its share needs all three of DisplayRoot, Root and the WMI ProviderName, because which one is populated depends on how the drive was made: net use mappings (what GE-Enforce creates) fill DisplayRoot, while a New-PSDrive to a UNC leaves DisplayRoot EMPTY and puts the share in Root. A local drive and an already-UNC path both fall through untouched. --- .../common/scripts/Backup-PartMarker.ps1 | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/playbook/shopfloor-setup/common/scripts/Backup-PartMarker.ps1 b/playbook/shopfloor-setup/common/scripts/Backup-PartMarker.ps1 index 9f4c217..e11e57b 100644 --- a/playbook/shopfloor-setup/common/scripts/Backup-PartMarker.ps1 +++ b/playbook/shopfloor-setup/common/scripts/Backup-PartMarker.ps1 @@ -179,6 +179,61 @@ function Get-SnapshotManifest { } +function ConvertTo-UncPath { + <# + .SYNOPSIS + The UNC equivalent of a path on a mapped drive, or the path unchanged. + .DESCRIPTION + We WRITE through the drive letter GE-Enforce mapped, because that is the + connection it authenticated - reaching the same server by another name + can cost a second authentication or fail outright with error 1219. + + But the path RECORDED in ShopDB has to be one a human can use. "W:" is a + mapping that exists only inside the SYSTEM session, only while the cycle + runs, and only on that one PC. Storing it means a tech opening the + marker's page gets a path that resolves to nothing anywhere. + + So: write by drive, record by UNC. DisplayRoot on a mapped PSDrive is + the share it points at; a local drive has none, and a path that is + already UNC needs no help - both fall through unchanged. + #> + param([Parameter(Mandatory)][string]$Path) + + if ($Path -like '\\*') { return $Path } + + $qualifier = '' + try { $qualifier = Split-Path -Qualifier $Path } catch { return $Path } + if (-not $qualifier) { return $Path } + + $letter = $qualifier.TrimEnd(':') + $rest = Split-Path -NoQualifier $Path + + # Three ways a drive can tell you where it points, and which one is + # populated depends on how it was created: + # DisplayRoot set by `net use` mappings - what GE-Enforce makes + # Root set by New-PSDrive to a UNC, where DisplayRoot is EMPTY + # ProviderName the WMI view, as a backstop if the PSDrive lookup is odd + try { + $drive = Get-PSDrive -Name $letter -ErrorAction Stop + foreach ($candidate in @($drive.DisplayRoot, $drive.Root)) { + if ($candidate -and $candidate -like '\\*') { + return ($candidate.TrimEnd('\') + $rest) + } + } + } catch { } + + try { + $disk = Get-CimInstance -ClassName Win32_LogicalDisk ` + -Filter ("DeviceID='{0}:'" -f $letter) -ErrorAction Stop + if ($disk.ProviderName -and $disk.ProviderName -like '\\*') { + return ($disk.ProviderName.TrimEnd('\') + $rest) + } + } catch { } + + return $Path +} + + # ============================================================================= # Main # ============================================================================= @@ -485,8 +540,16 @@ foreach ($property in (ConvertFrom-Json $manifestjson).PSObject.Properties) { $manifesthash[$property.Name] = $property.Value } +# Written through $snapshotdir (the mapped drive), recorded as UNC so the path +# stored against the marker means something on any PC, at any time. +$reportedpath = ConvertTo-UncPath -Path $snapshotdir +if ($reportedpath -ne $snapshotdir) { + Write-ShopdbBackupLog -Kind $KIND -Message ( + 'Recording {0} (written through {1})' -f $reportedpath, $snapshotdir) +} + $posted = Send-ShopdbBackup -Context $ctx ` - -ContentHash $manifest.ManifestHash -SharePath $snapshotdir ` + -ContentHash $manifest.ManifestHash -SharePath $reportedpath ` -SourceFileName 'manifest.json' -Manifest $manifesthash -TimeoutSec $TimeoutSec # Send-ShopdbBackup logs created vs noop. On a no-op the directory just written