From b86b83056881d4ad96f9ef0c586d205acc6a328e Mon Sep 17 00:00:00 2001 From: cproudlock Date: Fri, 22 May 2026 09:17:07 -0400 Subject: [PATCH] Run-ShopfloorSetup: self-resume RunOnce + top up AutoLogonCount Imaging chain stalled on WJF00159 after FormTracePak Setup.exe forced a reboot: SupportUser auto-logged in fine, briefly flashed something (an HKLM\Run logon hook), then idle - no resume of Run-ShopfloorSetup. Confirmed via diag-dispatcher.ps1: bay had AutoLogon working, RunOnce empty, no Stage-Dispatcher.ps1 on disk, no setup-stage.txt. Root cause: Run-ShopfloorSetup launches once from unattend XML's FirstLogonCommands and has no self-resume mechanism. If anything cuts it off mid-flight (FormTracePak Setup, eDNC MSI, Oracle install with forced reboot, etc) the chain dies and nothing brings it back. Stage-Dispatcher.ps1 in the repo is academic infrastructure that was never wired into the live flow - startnet.cmd does not stage it and nothing creates setup-stage.txt. Fix: have Run-ShopfloorSetup register ITSELF as RunOnce at the top of the script. The script is idempotent throughout (detection checks skip already-done work) so re-entry post-reboot picks up cleanly. Normal completion path removes the RunOnce so it does not re-fire after the planned end-of-script reboot. Also top up AutoLogonCount to 10 at script start. The unattend XML's LogonCount=7 budget gets consumed across typical imaging reboots (Office, Oracle, FormTracePak, Run-ShopfloorSetup explicit, sync-intune) and an unplanned FormTracePak forced reboot pushes the counter past 0, clearing AutoAdminLogon and parking the bay at the login screen. Restoring the budget every Run-ShopfloorSetup entry keeps SupportUser auto-logging in across any number of forced reboots until normal completion. Lockdown's Autologon.exe sets its own AutoAdminLogon for the ShopFloor user when it runs, so the post-completion natural decrement to 0 does not affect the final state. Verified via diag-dispatcher.ps1 capture on WJF00159 today - that bay had AutoLogonCount=4 and no Stage-Dispatcher.ps1 on disk, which both match this root cause + fix. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../shopfloor-setup/Run-ShopfloorSetup.ps1 | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 b/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 index fee2da9..800b60f 100644 --- a/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 +++ b/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 @@ -50,6 +50,35 @@ Report-Stage -Stage 'Run-ShopfloorSetup: starting' -Index 2 # Cancel any pending reboot so it doesn't interrupt setup cmd /c "shutdown /a 2>nul" *>$null +# Self-resume: register this script as a RunOnce so a vendor-installer- +# forced reboot mid-flight (FormTracePak Setup.exe, eDNC MSI, etc) auto- +# resumes the chain after the next SupportUser auto-login. RunOnce is +# single-shot - if we complete normally we remove this key at end of +# script. If we're killed mid-flight by a forced reboot, the key +# survives and fires after reboot. +# +# Idempotent design throughout this script: every step checks detection +# before installing, so a forced-reboot re-entry just skips the already- +# done work and continues from where it left off. +# +# Also top up AutoLogonCount so the SupportUser autologon budget +# (LogonCount=7 from unattend XML) survives extra unplanned reboots. +$selfResumeKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce' +$selfResumeName = 'ResumeRunShopfloorSetup' +$selfResumeCmd = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -File "' + $PSCommandPath + '"' +try { + Set-ItemProperty -Path $selfResumeKey -Name $selfResumeName -Value $selfResumeCmd -Type String -Force -ErrorAction Stop + Write-Host "Self-resume RunOnce registered: will re-fire $PSCommandPath if interrupted" +} catch { + Write-Warning "Failed to register self-resume RunOnce: $_" +} +try { + Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name 'AutoLogonCount' -Value 10 -Type DWord -Force -ErrorAction Stop + Write-Host "AutoLogonCount topped up to 10 (vendor-forced reboot resilience)" +} catch { + Write-Warning "Failed to top up AutoLogonCount: $_" +} + # Wired NIC state handling moved to sync_intune (Monitor-IntuneProgress.ps1). # Previously this script prompted the tech to unplug the PXE cable and # then re-enabled wired adapters interactively - that blocked the whole @@ -450,6 +479,10 @@ if (Test-Path -LiteralPath $enrollScript) { Report-Stage -Stage 'Run-ShopfloorSetup: handoff to Monitor-IntuneProgress' -Index 6 Write-Host "=== Handing off to Monitor-IntuneProgress -PostPpkg ===" cmd /c "shutdown /a 2>nul" | Out-Null + # Made it past all the reboot-prone vendor installers. Clear the + # self-resume RunOnce so a normal completion + reboot does not re-fire + # this script post-PPKG (PPKG install owns the reboot chain from here). + try { Remove-ItemProperty -Path $selfResumeKey -Name $selfResumeName -ErrorAction SilentlyContinue } catch {} $monitor = Join-Path $setupDir 'Shopfloor\lib\Monitor-IntuneProgress.ps1' if (Test-Path -LiteralPath $monitor) { & powershell.exe -NoProfile -ExecutionPolicy Bypass -File $monitor -PostPpkg @@ -463,6 +496,7 @@ if (Test-Path -LiteralPath $enrollScript) { Write-Host "================================================================" Write-Host "=== Run-ShopfloorSetup.ps1 complete $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') ===" Write-Host "================================================================" + try { Remove-ItemProperty -Path $selfResumeKey -Name $selfResumeName -ErrorAction SilentlyContinue } catch {} try { Stop-Transcript | Out-Null } catch {} Write-Host "Rebooting in 10 seconds..." shutdown /r /t 10