Files
pxe-server/playbook/winpe-status-push.ps1
cproudlock a94c20331a Imaging floor: Standard/Engineer builds report progress past WinPE
The floor's 8 stages are the shopfloor pipeline, and only shopfloor-setup
reports after WinPE, so every gea-standard / gea-engineer build sat at
1/8 forever with no type.

- winpe-status-push.ps1 reads the image from the Z: share mapping when no
  PCTYPE is set and reports those builds as 5 steps.
- Send-ImagingStage.ps1 (deployed to _shared\Applications\extra\pxe-status)
  posts steps 2-5 from the unattend: start and end of specialize, first
  logon, and setup complete (succeeded). It is copied to
  C:\ProgramData\PxeStatus first, because the bulk-enrollment task deletes
  C:\Deploy before first logon. Best-effort: always exits 0.
- Floor rows use Standard/Engineer labels and show the image as the kind.

Tested as SYSTEM in the win11 VM (PowerShell 5.1): the exact unattend
command line, stages 3-5 against a test server, a dead port (exit 0), and
the image regex.
2026-10-14 16:23:52 -04:00

91 lines
3.0 KiB
PowerShell

# winpe-status-push.ps1 - Posts "WinPE: PESetup / WIM apply" status to the
# PXE webapp /imaging/status endpoint so the imaging dashboard reflects
# this bay BEFORE Run-ShopfloorSetup.ps1 takes over post-PPKG.
#
# Runs in WinPE's stripped PowerShell - cannot rely on Get-NetAdapter,
# Get-CimInstance, or the NetTCPIP module (none are present in stock
# WinPE). Uses wmic for both serial and MAC.
#
# Best-effort: never blocks imaging. All steps log to
# X:\Windows\Temp\winpe-status-push.log; failures are swallowed.
param(
[string]$PxeServer = '172.16.9.1',
[int]$Port = 9009,
[int]$TimeoutSec = 5,
[string]$PCType = $env:PCTYPE,
[string]$CurrentStage = 'WinPE: PESetup / WIM apply',
[int]$StageIndex = 1
)
$logFile = 'X:\Windows\Temp\winpe-status-push.log'
function Log {
param([string]$msg)
try { "$(Get-Date -Format s) $msg" | Out-File -FilePath $logFile -Append -Encoding utf8 } catch { }
}
Log "=== winpe-status-push start ==="
Log "server=${PxeServer}:${Port} pctype=$PCType"
# Serial via wmic. Always available in WinPE 10+.
$serial = ''
try {
$line = (& wmic bios get serialnumber /value 2>$null | Where-Object { $_ -match '=' } | Select-Object -First 1)
if ($line) { $serial = ($line -split '=', 2)[1].Trim() }
} catch { Log "serial wmic exception: $_" }
Log "serial=$serial"
# MAC via wmic NIC enumeration. NetEnabled filter restricts to up adapters.
$mac = ''
try {
$macLines = & wmic nic where 'NetEnabled=TRUE' get MacAddress /value 2>$null |
Where-Object { $_ -match 'MacAddress=' }
if ($macLines) {
$first = ($macLines | Select-Object -First 1)
$mac = (($first -split '=', 2)[1]).Trim() -replace '-', ':'
}
} catch { Log "mac wmic exception: $_" }
Log "mac=$mac"
if (-not $serial) {
Log "no serial captured - aborting POST"
exit 0
}
# 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.
$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 }
} catch { Log "net use Z: exception: $_" }
Log "image from Z: = '$PCType'"
}
# Compose JSON. ConvertTo-Json works in WinPE.
$payload = @{
serial = $serial
pctype = $PCType
current_stage = $CurrentStage
stage_index = $StageIndex
stage_total = $total
status = 'in_progress'
}
if ($mac) { $payload.mac = $mac }
$body = $payload | ConvertTo-Json -Compress
$uri = "http://${PxeServer}:${Port}/imaging/status"
Log "POST $uri body=$body"
try {
$resp = Invoke-WebRequest -Uri $uri -Method POST -Body $body `
-ContentType 'application/json' -UseBasicParsing -TimeoutSec $TimeoutSec -ErrorAction Stop
Log "OK http=$($resp.StatusCode)"
} catch {
Log "ERR $($_.Exception.Message)"
}
exit 0