Standard/Engineer builds are done at OOBE on the imaging floor

Everything after OOBE needs the employee to log in, which happens off the
PXE network, so the floor waited forever at step 3 of 5. Now 3 steps:
WinPE, Windows setup installing apps, ready at OOBE (succeeded).

- both unattends: specialize Order 49 posts step 3 as succeeded
  (Path 182 chars; lint clean). Only that line changed.
- Send-ImagingStage.ps1: StageTotal 3; steps above the total (the old
  first-logon steps 4 and 5 still in the unattends) are logged and not
  posted, so they cannot reopen a finished build
- winpe-status-push.ps1: total 3 for gea-standard / gea-engineer
- floor tile step 3: "Ready at OOBE"

Tested in the win11 VM against the test server: steps 2 and 3 post,
step 3 shows succeeded, step 4 is skipped. Not deployed: the unattends
go out only through scripts/deploy-unattend.sh.
This commit is contained in:
cproudlock
2026-10-16 10:09:40 -04:00
parent bca04f4ca2
commit 9d75d03b2d
5 changed files with 24 additions and 11 deletions

View File

@@ -311,8 +311,8 @@
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>49</Order>
<Path>powershell.exe -NoP -EP Bypass -File C:\ProgramData\PxeStatus\Send-ImagingStage.ps1 -PCType gea-engineer -StageIndex 3 -Stage "Apps installed - waiting for first logon"</Path>
<Description>PXE status: stage 3 of 5</Description>
<Path>powershell.exe -NoP -EP Bypass -File C:\ProgramData\PxeStatus\Send-ImagingStage.ps1 -PCType gea-engineer -StageIndex 3 -Status succeeded -Stage "Ready at OOBE - hand to the employee"</Path>
<Description>PXE status: stage 3 of 3, done (the rest needs the employee to log in)</Description>
</RunSynchronousCommand>
</RunSynchronous>
</component>

View File

@@ -311,8 +311,8 @@
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>49</Order>
<Path>powershell.exe -NoP -EP Bypass -File C:\ProgramData\PxeStatus\Send-ImagingStage.ps1 -PCType gea-standard -StageIndex 3 -Stage "Apps installed - waiting for first logon"</Path>
<Description>PXE status: stage 3 of 5</Description>
<Path>powershell.exe -NoP -EP Bypass -File C:\ProgramData\PxeStatus\Send-ImagingStage.ps1 -PCType gea-standard -StageIndex 3 -Status succeeded -Stage "Ready at OOBE - hand to the employee"</Path>
<Description>PXE status: stage 3 of 3, done (the rest needs the employee to log in)</Description>
</RunSynchronousCommand>
</RunSynchronous>
</component>

View File

@@ -13,11 +13,17 @@
# Best-effort: never blocks or fails Windows setup. Every error is swallowed,
# the script always exits 0, and each attempt is logged to
# C:\Logs\send-imaging-stage.log.
#
# Three steps: 1 WinPE, 2 Windows setup installing apps, 3 ready at OOBE
# (succeeded). Everything after OOBE needs the employee to log in, which
# happens off the PXE network, so PXE cannot see it. Steps above
# StageTotal (the old first-logon steps 4 and 5 still in the unattends) are
# logged and not posted, so they cannot reopen a finished build.
param(
[Parameter(Mandatory = $true)][string]$Stage,
[int]$StageIndex = 0,
[int]$StageTotal = 5,
[int]$StageTotal = 3,
[string]$PCType = '',
[ValidateSet('in_progress', 'succeeded', 'failed')][string]$Status = 'in_progress',
[string]$PxeServer = '172.16.9.1',
@@ -43,6 +49,11 @@ if ($Persist) {
} catch { Log "persist failed: $($_.Exception.Message)" }
}
if ($StageIndex -gt $StageTotal) {
Log "SKIP stage $StageIndex of $StageTotal (after OOBE; PXE does not track it): $Stage"
exit 0
}
try {
$serial = $null
try { $serial = (Get-CimInstance -ClassName Win32_BIOS -ErrorAction Stop).SerialNumber } catch {

View File

@@ -61,17 +61,17 @@ if (-not $serial) {
# gea-standard / gea-engineer set no PCTYPE: read the image from the share
# startnet mapped as Z: (\\server\winpeapps\<image>). Those builds report
# 5 steps (WinPE, then Send-ImagingStage.ps1 from their unattend); the
# shopfloor build reports 8.
# 3 steps (WinPE, then Send-ImagingStage.ps1 from their unattend, done
# at OOBE); the shopfloor build reports 8.
$total = 8
if (-not $PCType) {
try {
$z = (& net use Z: 2>$null | Out-String)
if ($z -match 'winpeapps\\(gea-standard|gea-engineer)\b') { $PCType = $Matches[1]; $total = 5 }
if ($z -match 'winpeapps\\(gea-standard|gea-engineer)\b') { $PCType = $Matches[1]; $total = 3 }
} catch { Log "net use Z: exception: $_" }
Log "image from Z: = '$PCType'"
}
if ($PCType -in @('gea-standard', 'gea-engineer')) { $total = 5 }
if ($PCType -in @('gea-standard', 'gea-engineer')) { $total = 3 }
# Say so from the first push: the BIOS update was staged before the menu, but
# startnet's own "BIOS firmware update" push only comes at the end of WinPE.

View File

@@ -18,11 +18,13 @@
} %}
{# gea-standard / gea-engineer builds: WinPE push, then
Send-ImagingStage.ps1 from the image's unattend; stage_total 5. #}
Send-ImagingStage.ps1 from the image's unattend; stage_total 3. Done
at OOBE: everything after needs the employee's logon, off the PXE
network. (4 and 5 are kept for builds still running the old unattend.) #}
{% set desk_stage_labels = {
1: ('Applying Windows image', 'WinPE loaded - PESetup is applying the Windows image to disk.'),
2: ('Windows setup: installing apps','First boot (specialize): certificates, WiFi, fonts, Adobe, Java and the enrollment task.'),
3: ('Waiting for first logon', 'Apps installed. Windows setup finishes when someone logs on to the PC.'),
3: ('Ready at OOBE', 'PXE imaging is done. Hand the PC to the employee: first logon (and the engineering layer on Engineer builds) runs when they sign in.'),
4: ('First logon', 'First logon commands running (the engineering layer on Engineer builds).'),
5: ('Setup complete', 'Imaging is done; bulk enrollment continues on the PC.')
} %}