shopfloor: stop manifest entries hijacking GE-Enforce's drive letter
GE-Enforce mounts the SFLD share on W: and holds it for the whole enforce cycle, passing W:\<pctype> as -InstallerRoot to Install-FromManifest. Two scripts that run inside that cycle, as SYSTEM in the same drive namespace, mapped W: for their own use and deleted it on exit: Restore-UDCData.ps1 manifest PS1 entry, mounts the UDC backup share Update-MachineNumber.ps1 "Apply Machine Number" task, same backup share Once W: is gone, the next manifest entry's Join-Path resolves against a dead drive qualifier. In Windows PowerShell 5.1 that emits nothing rather than throwing, so the null lands in Test-Path -LiteralPath and the entry dies with "Cannot bind argument to parameter 'LiteralPath' because it is null". Observed on a collections bay: the controller-credential entry, which runs immediately after UDC Data Restore, failed this way while the entry one line earlier had resolved a W: path successfully one second before. Restore-UDCData now uses R: and Update-MachineNumber uses N: for the UDC backup share. Neither letter is referenced anywhere else in the tree; V: was not an option because Restore-EDncReg and Update-MachineNumber's NTLARS restore already use it. The re-mount at GE-Enforce.ps1:239-244 does not cover this. It runs after the manifest loop and blames idle SMB timeout, but the whole cycle took one second, so timeout was never the cause.
This commit is contained in:
@@ -163,10 +163,13 @@ function Update-MachineNumber {
|
||||
}
|
||||
if ($udcSharePath) {
|
||||
try {
|
||||
$mountedUdc = Mount-SFLDShare -SharePath $udcSharePath -DriveLetter 'W:'
|
||||
# N:, never W:. GE-Enforce owns W: for its whole cycle, and this
|
||||
# runs as SYSTEM in the same drive namespace - taking W: here kills
|
||||
# the share out from under an in-flight enforce cycle.
|
||||
$mountedUdc = Mount-SFLDShare -SharePath $udcSharePath -DriveLetter 'N:'
|
||||
if ($mountedUdc) {
|
||||
try {
|
||||
$bayDir = Join-Path 'W:\' $NewNumber
|
||||
$bayDir = Join-Path 'N:\' $NewNumber
|
||||
$srcCur = Join-Path $bayDir 'CurrentData.json'
|
||||
$srcArc = Join-Path $bayDir 'ArchivedData'
|
||||
if (Test-Path -LiteralPath $srcCur) {
|
||||
@@ -226,7 +229,7 @@ function Update-MachineNumber {
|
||||
Write-Host " Update-MachineNumber: no UDC backup at $bayDir (fresh PC, no prior data)"
|
||||
}
|
||||
} finally {
|
||||
& net use W: /delete /y 2>$null | Out-Null
|
||||
& net use N: /delete /y 2>$null | Out-Null
|
||||
}
|
||||
} else {
|
||||
Write-Host " Update-MachineNumber: UDC backup share unreachable - skipping UDC restore."
|
||||
|
||||
@@ -147,7 +147,7 @@ if (-not $mn -or $mn -eq '9999' -or $mn -notmatch '^\d+$') {
|
||||
function Mount-SFLDShare {
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$SharePath,
|
||||
[string]$DriveLetter = 'V:'
|
||||
[string]$DriveLetter = 'R:'
|
||||
)
|
||||
$server = ($SharePath -replace '^\\\\', '') -split '\\' | Select-Object -First 1
|
||||
$basePath = 'HKLM:\SOFTWARE\GE\SFLD\Credentials'
|
||||
@@ -178,11 +178,18 @@ function Mount-SFLDShare {
|
||||
return ($LASTEXITCODE -eq 0)
|
||||
}
|
||||
|
||||
Log "Mounting share with SFLD creds: $BackupShareRoot -> W:"
|
||||
# R:, not W: and not V:. GE-Enforce owns W: for the whole enforce cycle
|
||||
# (GE-Enforce.ps1 $driveLetter). This script runs as a manifest PS1 entry
|
||||
# inside that cycle, so remapping/deleting W: here kills the share for every
|
||||
# later manifest entry - Join-Path on a dead W: returns null and the next
|
||||
# entry dies with "Cannot bind argument to parameter 'LiteralPath' because it
|
||||
# is null". V: is no good either: Update-MachineNumber.ps1 / Restore-EDncReg.ps1
|
||||
# mount V: and run as SYSTEM in the same drive namespace. R: is unclaimed.
|
||||
Log "Mounting share with SFLD creds: $BackupShareRoot -> R:"
|
||||
$shareMounted = $false
|
||||
$sw = [Diagnostics.Stopwatch]::StartNew()
|
||||
while ($sw.Elapsed.TotalSeconds -lt $ShareTimeoutSec) {
|
||||
if (Mount-SFLDShare -SharePath $BackupShareRoot -DriveLetter 'W:') {
|
||||
if (Mount-SFLDShare -SharePath $BackupShareRoot -DriveLetter 'R:') {
|
||||
$shareMounted = $true
|
||||
break
|
||||
}
|
||||
@@ -190,16 +197,16 @@ while ($sw.Elapsed.TotalSeconds -lt $ShareTimeoutSec) {
|
||||
}
|
||||
$sw.Stop()
|
||||
if ($shareMounted) {
|
||||
Log ("Share mounted as W: after {0:N1} s" -f $sw.Elapsed.TotalSeconds)
|
||||
Log ("Share mounted as R: after {0:N1} s" -f $sw.Elapsed.TotalSeconds)
|
||||
} else {
|
||||
Log "Mount-SFLDShare failed after $ShareTimeoutSec s. SFLD creds may be missing in HKLM:\SOFTWARE\GE\SFLD\Credentials, or the share is unreachable. Exiting non-zero so the dispatcher logs a failure." 'ERROR'
|
||||
Log 'Exit 1.'
|
||||
exit 1
|
||||
}
|
||||
|
||||
# All bay-level paths now go through W: (authenticated as SFLD user) so
|
||||
# All bay-level paths now go through R: (authenticated as SFLD user) so
|
||||
# Test-Path returns the truth, not access-denied-False.
|
||||
$bayDir = Join-Path 'W:\' $mn
|
||||
$bayDir = Join-Path 'R:\' $mn
|
||||
$srcCur = Join-Path $bayDir 'CurrentData.json'
|
||||
$srcArc = Join-Path $bayDir 'ArchivedData'
|
||||
Log "Probing backup paths for bay $mn"
|
||||
@@ -213,7 +220,7 @@ Log " ArchivedData/ src: $(if ($srcArcExists) { 'present' } else { 'absent'
|
||||
|
||||
if (-not $srcCurExists -and -not $srcArcExists) {
|
||||
Log "No backup waiting for bay $mn (neither CurrentData.json nor ArchivedData\ at bay root) - no work to do this cycle."
|
||||
& net use W: /delete /y 2>$null | Out-Null
|
||||
& net use R: /delete /y 2>$null | Out-Null
|
||||
Log 'Exit 0.'
|
||||
exit 0
|
||||
}
|
||||
@@ -251,7 +258,7 @@ if (-not (Test-Path -LiteralPath $UdcDataDir)) {
|
||||
} catch {
|
||||
Log "Failed to create $UdcDataDir - cannot continue" 'ERROR'
|
||||
LogErr $_
|
||||
& net use W: /delete /y 2>$null | Out-Null
|
||||
& net use R: /delete /y 2>$null | Out-Null
|
||||
Log 'Exit 1.'
|
||||
exit 1
|
||||
}
|
||||
@@ -376,7 +383,7 @@ if ((Test-Path -LiteralPath $UdcExePath) -and ($copiedCur -or $copiedArc)) {
|
||||
}
|
||||
|
||||
# Unmount the SFLD-creds-mounted drive so we don't leave a stale net-use entry
|
||||
& net use W: /delete /y 2>$null | Out-Null
|
||||
& net use R: /delete /y 2>$null | Out-Null
|
||||
|
||||
Log 'Exit 0.'
|
||||
Log '==============================================='
|
||||
|
||||
Reference in New Issue
Block a user