# Apply-MachineNumber.ps1 - SYSTEM-context worker for the two-task machine # number flow. Triggered on-demand by Prompt-MachineNumber.ps1 via # `schtasks /run /tn "WT-Apply-MachineNumber"`. Reads the requested number # from a file the GUI script wrote, invokes Update-MachineNumber as SYSTEM # (full HKLM + ProgramData access), writes a result JSON for the GUI to # display, then cleans up. # # Why SYSTEM: # The eDNC reg key (HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\ # General\MachineNo) and UDC settings JSON live in HKLM + ProgramData # respectively - both require admin to write. The OLD design granted # BUILTIN\Users SetValue + Modify via 02-MachineNumberACLs.ps1, but that # was fragile (timing race with eDNC install, ACL silently failed on # some bays) AND a security hole (any user could mess with the machine # identity). Two-task design: GUI gathers input as logged-in user, SYSTEM # does the actual write. # # Files: # C:\Logs\SFLD\machine-number-request.txt - input, single line, new number # C:\Logs\SFLD\machine-number-result.json - output, status fields for GUI # C:\Logs\SFLD\Apply-MachineNumber.log - transcript $ErrorActionPreference = 'Continue' $logDir = 'C:\Logs\SFLD' if (-not (Test-Path -LiteralPath $logDir)) { try { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } catch { $logDir = $env:TEMP } } $transcript = Join-Path $logDir 'Apply-MachineNumber.log' try { Start-Transcript -Path $transcript -Append -Force | Out-Null } catch {} $requestFile = Join-Path $logDir 'machine-number-request.txt' $resultFile = Join-Path $logDir 'machine-number-result.json' function Write-Result { param([hashtable]$Body) $Body | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath $resultFile -Encoding ascii -Force } Write-Host "Apply-MachineNumber.ps1 starting $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" Write-Host "Running as: $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)" try { if (-not (Test-Path -LiteralPath $requestFile)) { Write-Warning "No request file at $requestFile - nothing to apply." Write-Result @{ Status = 'NoRequest'; Errors = @("request file missing: $requestFile") } exit 0 } $newNumber = (Get-Content -LiteralPath $requestFile -First 1 -ErrorAction Stop).Trim() Write-Host "Requested new machine number: $newNumber" if ($newNumber -notmatch '^\d+$') { Write-Warning "Request is not digits-only: '$newNumber'" Write-Result @{ Status = 'BadInput'; Requested = $newNumber; Errors = @("Not digits only: '$newNumber'") } Remove-Item -LiteralPath $requestFile -Force -ErrorAction SilentlyContinue exit 1 } # Dot-source the shared helper. Update-MachineNumber.ps1 now has # -ErrorAction Stop on the writes so failures actually throw. . "$PSScriptRoot\lib\Get-PCProfile.ps1" . "$PSScriptRoot\lib\Update-MachineNumber.ps1" $site = if ($siteConfig) { $siteConfig.siteName } else { 'West Jefferson' } $mnResult = Update-MachineNumber -NewNumber $newNumber -Site $site $resultBody = @{ Status = if ($mnResult.Errors.Count -eq 0) { 'OK' } else { 'PartialErrors' } Requested = $newNumber Site = $site UdcUpdated = [bool]$mnResult.UdcUpdated EdncUpdated = [bool]$mnResult.EdncUpdated OldUdc = $mnResult.OldUdc OldEdnc = $mnResult.OldEdnc UdcSettingsRestored = [bool]$mnResult.UdcSettingsRestored UdcRestored = [bool]$mnResult.UdcRestored MTConnectUpdated = $mnResult.MTConnectUpdated MachineNumberTxtUpdated = [bool]$mnResult.MachineNumberTxtUpdated Errors = $mnResult.Errors AppliedAt = (Get-Date -Format 'o') AppliedAs = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name } Write-Result -Body $resultBody Write-Host "Update-MachineNumber result:" Write-Host " UdcUpdated = $($mnResult.UdcUpdated)" Write-Host " EdncUpdated = $($mnResult.EdncUpdated)" Write-Host " Errors = $($mnResult.Errors.Count)" if ($mnResult.Errors) { $mnResult.Errors | ForEach-Object { Write-Host " FAILED: $_" } } Remove-Item -LiteralPath $requestFile -Force -ErrorAction SilentlyContinue # On clean success, also unregister the Prompt logon task. Prompt itself # tries to self-unregister but it runs as a Limited user (BUILTIN\Users) # and silently fails on Unregister-ScheduledTask (no delete right on a # SYSTEM-registered task). We're running as SYSTEM here, so we can. # Idempotent if Prompt already unregistered itself somehow. if ($mnResult.Errors.Count -eq 0 -and $mnResult.EdncUpdated) { try { if (Get-ScheduledTask -TaskName 'Prompt Machine Number' -ErrorAction SilentlyContinue) { Unregister-ScheduledTask -TaskName 'Prompt Machine Number' -Confirm:$false -ErrorAction Stop Write-Host "Unregistered 'Prompt Machine Number' task (SYSTEM cleanup)." } } catch { Write-Host "Could not unregister 'Prompt Machine Number': $_" } } Write-Host "Apply-MachineNumber.ps1 finished $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" } catch { Write-Warning "Apply threw: $_" Write-Result @{ Status = 'Exception'; Errors = @("$_") } } finally { try { Stop-Transcript | Out-Null } catch {} }