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.
This commit is contained in:
@@ -61,6 +61,13 @@
|
||||
<Path>cmd /c sc config wlansvc start= auto & net start wlansvc & exit /b 0</Path>
|
||||
<Description>Start WLAN AutoConfig so the WiFi profile can be added</Description>
|
||||
</RunSynchronousCommand>
|
||||
<!-- PXE imaging floor progress (best-effort, never fails setup). The script is copied
|
||||
out of C:\Deploy here because the bulk-enrollment task deletes C:\Deploy later. -->
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<Path>cmd /c (if not exist C:\ProgramData\PxeStatus mkdir C:\ProgramData\PxeStatus) & copy /Y "C:\Deploy\Applications\extra\pxe-status\Send-ImagingStage.ps1" C:\ProgramData\PxeStatus\ & powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\PxeStatus\Send-ImagingStage.ps1" -PCType gea-engineer -StageIndex 2 -StageTotal 5 -Stage "Windows setup: installing apps" -Status in_progress & exit /b 0</Path>
|
||||
<Description>PXE status: stage 2 of 5</Description>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>3</Order>
|
||||
<Path>cmd /c netsh wlan add profile filename="C:\Deploy\Applications\extra\wireless\WiFi-Profile.xml" user=all</Path>
|
||||
@@ -301,6 +308,11 @@
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows\RemovableStorageDevices" /v Deny_All /t REG_DWORD /d 1 /f</Path>
|
||||
<Description>Block all removable media reads to prevent PPKG auto-detection at OOBE</Description>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>49</Order>
|
||||
<Path>powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\PxeStatus\Send-ImagingStage.ps1" -PCType gea-engineer -StageIndex 3 -StageTotal 5 -Stage "Apps installed - waiting for first logon" -Status in_progress</Path>
|
||||
<Description>PXE status: stage 3 of 5</Description>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
</settings>
|
||||
@@ -324,6 +336,11 @@
|
||||
<SkipMachineOOBE>false</SkipMachineOOBE>
|
||||
</OOBE>
|
||||
<FirstLogonCommands>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\PxeStatus\Send-ImagingStage.ps1" -PCType gea-engineer -StageIndex 4 -StageTotal 5 -Stage "First logon: installing engineering layer" -Status in_progress</CommandLine>
|
||||
<Description>PXE status: stage 4 of 5</Description>
|
||||
<Order>1</Order>
|
||||
</SynchronousCommand>
|
||||
|
||||
|
||||
|
||||
@@ -373,6 +390,11 @@
|
||||
detail lives here. -->
|
||||
<Description>Engineering Layer: stage payload out of C:\Deploy then install</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\PxeStatus\Send-ImagingStage.ps1" -PCType gea-engineer -StageIndex 5 -StageTotal 5 -Stage "Setup complete - enrollment continues on the PC" -Status succeeded</CommandLine>
|
||||
<Description>PXE status: stage 5 of 5</Description>
|
||||
<Order>12</Order>
|
||||
</SynchronousCommand>
|
||||
</FirstLogonCommands>
|
||||
</component>
|
||||
</settings>
|
||||
|
||||
@@ -61,6 +61,13 @@
|
||||
<Path>cmd /c sc config wlansvc start= auto & net start wlansvc & exit /b 0</Path>
|
||||
<Description>Start WLAN AutoConfig so the WiFi profile can be added</Description>
|
||||
</RunSynchronousCommand>
|
||||
<!-- PXE imaging floor progress (best-effort, never fails setup). The script is copied
|
||||
out of C:\Deploy here because the bulk-enrollment task deletes C:\Deploy later. -->
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<Path>cmd /c (if not exist C:\ProgramData\PxeStatus mkdir C:\ProgramData\PxeStatus) & copy /Y "C:\Deploy\Applications\extra\pxe-status\Send-ImagingStage.ps1" C:\ProgramData\PxeStatus\ & powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\PxeStatus\Send-ImagingStage.ps1" -PCType gea-standard -StageIndex 2 -StageTotal 5 -Stage "Windows setup: installing apps" -Status in_progress & exit /b 0</Path>
|
||||
<Description>PXE status: stage 2 of 5</Description>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>3</Order>
|
||||
<Path>cmd /c netsh wlan add profile filename="C:\Deploy\Applications\extra\wireless\WiFi-Profile.xml" user=all</Path>
|
||||
@@ -301,6 +308,11 @@
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows\RemovableStorageDevices" /v Deny_All /t REG_DWORD /d 1 /f</Path>
|
||||
<Description>Block all removable media reads to prevent PPKG auto-detection at OOBE</Description>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>49</Order>
|
||||
<Path>powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\PxeStatus\Send-ImagingStage.ps1" -PCType gea-standard -StageIndex 3 -StageTotal 5 -Stage "Apps installed - waiting for first logon" -Status in_progress</Path>
|
||||
<Description>PXE status: stage 3 of 5</Description>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
</settings>
|
||||
@@ -324,6 +336,11 @@
|
||||
<SkipMachineOOBE>false</SkipMachineOOBE>
|
||||
</OOBE>
|
||||
<FirstLogonCommands>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\PxeStatus\Send-ImagingStage.ps1" -PCType gea-standard -StageIndex 4 -StageTotal 5 -Stage "First logon" -Status in_progress</CommandLine>
|
||||
<Description>PXE status: stage 4 of 5</Description>
|
||||
<Order>1</Order>
|
||||
</SynchronousCommand>
|
||||
|
||||
|
||||
|
||||
@@ -362,6 +379,11 @@
|
||||
<Description>Restore removable media access after OOBE PPKG block</Description>
|
||||
<Order>10</Order>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\PxeStatus\Send-ImagingStage.ps1" -PCType gea-standard -StageIndex 5 -StageTotal 5 -Stage "Setup complete - enrollment continues on the PC" -Status succeeded</CommandLine>
|
||||
<Description>PXE status: stage 5 of 5</Description>
|
||||
<Order>11</Order>
|
||||
</SynchronousCommand>
|
||||
</FirstLogonCommands>
|
||||
</component>
|
||||
</settings>
|
||||
|
||||
73
playbook/imaging-status/Send-ImagingStage.ps1
Normal file
73
playbook/imaging-status/Send-ImagingStage.ps1
Normal file
@@ -0,0 +1,73 @@
|
||||
# Send-ImagingStage.ps1 - posts one progress step of a gea-standard /
|
||||
# gea-engineer build to the PXE webapp's /imaging/status endpoint, so the
|
||||
# imaging floor follows these builds past WinPE (the shopfloor build has its
|
||||
# own reporting in Shopfloor\lib\Send-PxeStatus.ps1).
|
||||
#
|
||||
# Called from the image's FlatUnattendW10.xml (specialize RunSynchronous and
|
||||
# oobeSystem FirstLogonCommands). Deployed to
|
||||
# _shared\Applications\extra\pxe-status\ on the PXE server, which PESetup
|
||||
# copies to C:\Deploy\Applications\extra\pxe-status\.
|
||||
#
|
||||
# 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.
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Stage,
|
||||
[int]$StageIndex = 0,
|
||||
[int]$StageTotal = 5,
|
||||
[string]$PCType = '',
|
||||
[ValidateSet('in_progress', 'succeeded', 'failed')][string]$Status = 'in_progress',
|
||||
[string]$PxeServer = '172.16.9.1',
|
||||
[int]$Port = 9009,
|
||||
[int]$TimeoutSec = 5
|
||||
)
|
||||
|
||||
$logFile = 'C:\Logs\send-imaging-stage.log'
|
||||
function Log([string]$msg) {
|
||||
try {
|
||||
if (-not (Test-Path 'C:\Logs')) { New-Item -ItemType Directory -Path 'C:\Logs' -Force | Out-Null }
|
||||
"$(Get-Date -Format s) $msg" | Out-File -FilePath $logFile -Append -Encoding utf8
|
||||
} catch { }
|
||||
}
|
||||
|
||||
try {
|
||||
$serial = $null
|
||||
try { $serial = (Get-CimInstance -ClassName Win32_BIOS -ErrorAction Stop).SerialNumber } catch {
|
||||
try { $serial = (Get-WmiObject -Class Win32_BIOS -ErrorAction Stop).SerialNumber } catch { }
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($serial)) { $serial = $env:COMPUTERNAME }
|
||||
$serial = ($serial -as [string]).Trim()
|
||||
|
||||
$mac = $null
|
||||
try {
|
||||
$nic = Get-NetAdapter -Physical -ErrorAction Stop |
|
||||
Where-Object { $_.Status -eq 'Up' -and $_.MediaType -eq '802.3' } | Select-Object -First 1
|
||||
if ($nic) { $mac = $nic.MacAddress -replace '-', ':' }
|
||||
} catch { }
|
||||
|
||||
$payload = @{
|
||||
serial = $serial
|
||||
hostname_target = $env:COMPUTERNAME
|
||||
current_stage = $Stage
|
||||
stage_index = $StageIndex
|
||||
stage_total = $StageTotal
|
||||
status = $Status
|
||||
}
|
||||
if ($PCType) { $payload.pctype = $PCType }
|
||||
if ($mac) { $payload.mac = $mac }
|
||||
$body = $payload | ConvertTo-Json -Compress
|
||||
$uri = "http://${PxeServer}:${Port}/imaging/status"
|
||||
|
||||
try {
|
||||
$resp = Invoke-WebRequest -Uri $uri -Method POST -Body $body -ContentType 'application/json' `
|
||||
-UseBasicParsing -TimeoutSec $TimeoutSec -ErrorAction Stop
|
||||
Log "OK $($resp.StatusCode) $body"
|
||||
} catch {
|
||||
# Off the imaging network (or the server is down): nothing to report to.
|
||||
Log "FAIL $($_.Exception.Message) $body"
|
||||
}
|
||||
} catch {
|
||||
Log "ERROR $($_.Exception.Message)"
|
||||
}
|
||||
exit 0
|
||||
@@ -52,13 +52,26 @@ if (-not $serial) {
|
||||
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 = 8
|
||||
stage_total = $total
|
||||
status = 'in_progress'
|
||||
}
|
||||
if ($mac) { $payload.mac = $mac }
|
||||
|
||||
@@ -17,6 +17,17 @@
|
||||
'Lockdown applied. Bay rebooted into ShopFloor session. Ready for production.')
|
||||
} %}
|
||||
|
||||
{# gea-standard / gea-engineer builds: WinPE push, then
|
||||
Send-ImagingStage.ps1 from the image's unattend; stage_total 5. #}
|
||||
{% 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.'),
|
||||
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.')
|
||||
} %}
|
||||
{% set desk_kind = {'gea-standard': 'Standard', 'gea-engineer': 'Engineer'} %}
|
||||
|
||||
{# Blancco Drive Eraser sessions (source/pctype "blancco"), posted by
|
||||
blancco-init.sh and blancco-progress.py; stage_total 7. #}
|
||||
{% set blancco_stage_labels = {
|
||||
@@ -69,7 +80,7 @@
|
||||
{% endif %}
|
||||
{% if stage_idx == 4 and s.status != 'failed' %}{% set warn = True %}{% endif %}
|
||||
{% else %}
|
||||
{% set friendly = stage_labels.get(stage_idx, ('Stage ' ~ stage_idx, '')) %}
|
||||
{% set friendly = (desk_stage_labels if s.pctype in desk_kind else stage_labels).get(stage_idx, ('Stage ' ~ stage_idx, '')) %}
|
||||
{% if stage_idx == 1 and s.current_stage and 'bios' in s.current_stage|lower %}
|
||||
{% set friendly = ('Updating BIOS: do not power off',
|
||||
'WinPE detected a firmware update for this model. Do NOT power off until the next reboot. Imaging continues afterward.') %}
|
||||
@@ -97,7 +108,7 @@
|
||||
{% if s.hostname_target and s.serial %}{% set _ = ident.append(s.hostname_target) %}{% endif %}
|
||||
{% if s.ip %}{% set _ = ident.append(s.ip) %}{% endif %}
|
||||
{% set title = s.serial or s.hostname_target or s.mac or s.ip or '(unknown bay)' %}
|
||||
{% set kind = 'Blancco wipe' if is_blancco else (s.pctype or '') %}
|
||||
{% set kind = 'Blancco wipe' if is_blancco else desk_kind.get(s.pctype, s.pctype or '') %}
|
||||
<div class="ui-row floor-row imaging-card" data-state="{{ state }}"
|
||||
data-serial="{{ s.serial or '' }}" data-key="{{ card_key }}" data-mac="{{ s.mac or '' }}"
|
||||
data-ip="{{ s.ip or '' }}" data-source="{{ s.source or 'client' }}"
|
||||
|
||||
Reference in New Issue
Block a user