Shopfloor unattend: move Orders 4/5 logic to external PS1 scripts
FlatUnattendW10-shopfloor.xml was rejected by Windows OOBE with
"the answer file is invalid" after the earlier tower-no-WiFi fix.
Root cause: the inline PowerShell in <CommandLine> for Orders 4 and
5 exceeded the SynchronousCommand CommandLine length limit (~1024
chars) and/or contained characters the unattend schema validator
dislikes.
Fix: move the logic to two external PS1 scripts and shrink both
CommandLine entries to ~85 chars each that just invoke the scripts.
- playbook/wait-for-internet.ps1: 60s interactive prompt ("connect
production network now"), then poll TCP 443 to login.microsoft-
online.us for up to 10 min with a hard timeout so the loop always
exits. Uses Test-NetConnection -Port 443 (not Test-Connection /
ICMP) because Microsoft 365 edges do not reliably respond to ping.
- playbook/migrate-to-wifi.ps1: Gates the entire wired-disable
migration on "does a WiFi adapter exist?" If not (tower), the
script is a no-op. If yes, disable wired / wait for WiFi internet
with a 5 min timeout / re-enable wired on timeout fallback.
- startnet.cmd stages both new scripts to W:\Enrollment\ next to
run-enrollment.ps1 during the WinPE phase.
- FlatUnattendW10-shopfloor.xml Orders 4 and 5 shrunk to short
invocations of C:\Enrollment\wait-for-internet.ps1 and
C:\Enrollment\migrate-to-wifi.ps1.
- startnet-template.cmd kept in sync.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -156,13 +156,13 @@
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>4</Order>
|
||||
<CommandLine>powershell.exe -ExecutionPolicy Bypass -Command "Write-Host ''; Write-Host '========================================' -ForegroundColor Yellow; Write-Host ' Connect to PRODUCTION network NOW' -ForegroundColor Yellow; Write-Host ' Towers: unplug PXE, plug into production' -ForegroundColor Yellow; Write-Host ' Laptops: WiFi should already be connected' -ForegroundColor Yellow; Write-Host '========================================' -ForegroundColor Yellow; Write-Host ''; Write-Host 'Auto-continuing in 60s (press any key to skip)...' -ForegroundColor Cyan; $end=(Get-Date).AddSeconds(60); while ((Get-Date) -lt $end) { if ($Host.UI.RawUI.KeyAvailable) { $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown'); break }; Start-Sleep -Milliseconds 500 }; Write-Host 'Waiting for internet connectivity (up to 10 min)...'; $end2=(Get-Date).AddMinutes(10); $ok=$false; while ((Get-Date) -lt $end2) { if (Test-NetConnection -ComputerName login.microsoftonline.us -Port 443 -InformationLevel Quiet -WarningAction SilentlyContinue) { $ok=$true; break }; Start-Sleep -Seconds 5 }; if ($ok) { Write-Host 'Internet connected.' -ForegroundColor Green } else { Write-Host 'Internet wait timeout - proceeding anyway.' -ForegroundColor Yellow }"</CommandLine>
|
||||
<Description>Prompt to connect production network, then wait for TCP 443 to login.microsoftonline.us (with 10 min timeout). Uses Test-NetConnection -Port 443 not Test-Connection because Microsoft 365 endpoints do not reliably respond to ICMP.</Description>
|
||||
<CommandLine>powershell.exe -ExecutionPolicy Bypass -File "C:\Enrollment\wait-for-internet.ps1"</CommandLine>
|
||||
<Description>Prompt to connect production network then wait for TCP 443 connectivity</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>5</Order>
|
||||
<CommandLine>powershell.exe -ExecutionPolicy Bypass -Command "$wifi = Get-NetAdapter -Physical -ErrorAction SilentlyContinue | Where-Object { $_.InterfaceDescription -match 'Wi-Fi|Wireless' }; if (-not $wifi) { Write-Host 'No WiFi adapter - staying on ethernet.' -ForegroundColor Cyan; exit 0 }; Get-NetAdapter -Physical | Where-Object { $_.InterfaceDescription -notmatch 'Wi-Fi|Wireless' } | Disable-NetAdapter -Confirm:$false; $end=(Get-Date).AddMinutes(5); $ok=$false; while ((Get-Date) -lt $end) { if (Test-NetConnection -ComputerName login.microsoftonline.us -Port 443 -InformationLevel Quiet -WarningAction SilentlyContinue) { $ok=$true; break }; Start-Sleep -Seconds 5 }; if ($ok) { Write-Host 'Internet confirmed over WiFi.' -ForegroundColor Green } else { Write-Host 'WiFi internet timeout - re-enabling ethernet.' -ForegroundColor Yellow; Get-NetAdapter -Physical | Where-Object { $_.InterfaceDescription -notmatch 'Wi-Fi|Wireless' } | Enable-NetAdapter -Confirm:$false }"</CommandLine>
|
||||
<Description>If WiFi adapter exists, migrate off wired onto WiFi for enrollment. Tower/desktop with no WiFi: skip entirely and stay on wired. Fall back to re-enabling wired if WiFi fails.</Description>
|
||||
<CommandLine>powershell.exe -ExecutionPolicy Bypass -File "C:\Enrollment\migrate-to-wifi.ps1"</CommandLine>
|
||||
<Description>Migrate from wired to WiFi if WiFi adapter present, else stay on wired</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>6</Order>
|
||||
|
||||
43
playbook/migrate-to-wifi.ps1
Normal file
43
playbook/migrate-to-wifi.ps1
Normal file
@@ -0,0 +1,43 @@
|
||||
# migrate-to-wifi.ps1 - Invoked by FlatUnattendW10-shopfloor.xml as Order 5
|
||||
# during first logon, right after wait-for-internet.ps1 and right before
|
||||
# GCCH enrollment. Moves the machine off wired onto WiFi for the rest of
|
||||
# the imaging chain so the PXE ethernet cable can be safely disconnected.
|
||||
#
|
||||
# Gated: if there is no physical Wi-Fi adapter on the machine (tower /
|
||||
# desktop case), the whole migration is a no-op. Previously this step
|
||||
# disabled all wired adapters unconditionally and then waited for WiFi
|
||||
# internet that could never arrive on towers, hanging first logon forever.
|
||||
|
||||
$wifi = Get-NetAdapter -Physical -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.InterfaceDescription -match 'Wi-Fi|Wireless' }
|
||||
|
||||
if (-not $wifi) {
|
||||
Write-Host 'No WiFi adapter - staying on ethernet.' -ForegroundColor Cyan
|
||||
exit 0
|
||||
}
|
||||
|
||||
Get-NetAdapter -Physical |
|
||||
Where-Object { $_.InterfaceDescription -notmatch 'Wi-Fi|Wireless' } |
|
||||
Disable-NetAdapter -Confirm:$false
|
||||
|
||||
$deadline = (Get-Date).AddMinutes(5)
|
||||
$ok = $false
|
||||
while ((Get-Date) -lt $deadline) {
|
||||
try {
|
||||
if (Test-NetConnection -ComputerName login.microsoftonline.us -Port 443 -InformationLevel Quiet -WarningAction SilentlyContinue) {
|
||||
$ok = $true
|
||||
break
|
||||
}
|
||||
} catch {}
|
||||
Start-Sleep -Seconds 5
|
||||
}
|
||||
|
||||
if ($ok) {
|
||||
Write-Host 'Internet confirmed over WiFi.' -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host 'WiFi internet timeout - re-enabling ethernet.' -ForegroundColor Yellow
|
||||
Get-NetAdapter -Physical |
|
||||
Where-Object { $_.InterfaceDescription -notmatch 'Wi-Fi|Wireless' } |
|
||||
Enable-NetAdapter -Confirm:$false
|
||||
}
|
||||
exit 0
|
||||
@@ -266,6 +266,8 @@ if errorlevel 1 (
|
||||
goto copy_pctype
|
||||
)
|
||||
copy /Y "Y:\run-enrollment.ps1" "W:\Enrollment\run-enrollment.ps1"
|
||||
copy /Y "Y:\wait-for-internet.ps1" "W:\Enrollment\wait-for-internet.ps1"
|
||||
copy /Y "Y:\migrate-to-wifi.ps1" "W:\Enrollment\migrate-to-wifi.ps1"
|
||||
|
||||
REM --- Create enroll.cmd at drive root as manual fallback ---
|
||||
> W:\enroll.cmd (
|
||||
|
||||
58
playbook/wait-for-internet.ps1
Normal file
58
playbook/wait-for-internet.ps1
Normal file
@@ -0,0 +1,58 @@
|
||||
# wait-for-internet.ps1 - Invoked by FlatUnattendW10-shopfloor.xml as Order 4
|
||||
# during first logon, right before GCCH enrollment. Previously the logic was
|
||||
# inline in the unattend's CommandLine attribute but the string exceeded
|
||||
# Microsoft's SynchronousCommand CommandLine length limit and Windows rejected
|
||||
# the whole answer file with "the answer file is invalid". Moved here to keep
|
||||
# the unattend CommandLine short.
|
||||
#
|
||||
# Behaviour:
|
||||
# 1. Print a 60-second prompt asking the tech to connect to production
|
||||
# network. Gives tower users a window to unplug PXE cable and re-cable
|
||||
# to a production port; laptop users are already on WiFi and can
|
||||
# press any key to skip.
|
||||
# 2. Poll TCP 443 to login.microsoftonline.us for up to 10 minutes using
|
||||
# Test-NetConnection (NOT Test-Connection / ICMP - Microsoft 365 edges
|
||||
# do not reliably respond to ICMP, which previously caused infinite
|
||||
# "Waiting for internet connectivity..." loops on towers).
|
||||
# 3. Always exit 0 so the unattend chain proceeds even if detection times
|
||||
# out - enrollment will retry on its own if the network is still broken.
|
||||
|
||||
Write-Host ''
|
||||
Write-Host '========================================' -ForegroundColor Yellow
|
||||
Write-Host ' Connect to PRODUCTION network NOW' -ForegroundColor Yellow
|
||||
Write-Host ' Towers: unplug PXE, plug into production' -ForegroundColor Yellow
|
||||
Write-Host ' Laptops: WiFi should already be connected' -ForegroundColor Yellow
|
||||
Write-Host '========================================' -ForegroundColor Yellow
|
||||
Write-Host ''
|
||||
Write-Host 'Auto-continuing in 60s (press any key to skip)...' -ForegroundColor Cyan
|
||||
|
||||
$end = (Get-Date).AddSeconds(60)
|
||||
while ((Get-Date) -lt $end) {
|
||||
try {
|
||||
if ($Host.UI.RawUI.KeyAvailable) {
|
||||
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
|
||||
break
|
||||
}
|
||||
} catch {}
|
||||
Start-Sleep -Milliseconds 500
|
||||
}
|
||||
|
||||
Write-Host 'Waiting for internet connectivity (up to 10 min)...'
|
||||
$deadline = (Get-Date).AddMinutes(10)
|
||||
$ok = $false
|
||||
while ((Get-Date) -lt $deadline) {
|
||||
try {
|
||||
if (Test-NetConnection -ComputerName login.microsoftonline.us -Port 443 -InformationLevel Quiet -WarningAction SilentlyContinue) {
|
||||
$ok = $true
|
||||
break
|
||||
}
|
||||
} catch {}
|
||||
Start-Sleep -Seconds 5
|
||||
}
|
||||
|
||||
if ($ok) {
|
||||
Write-Host 'Internet connected.' -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host 'Internet wait timeout - proceeding anyway.' -ForegroundColor Yellow
|
||||
}
|
||||
exit 0
|
||||
Reference in New Issue
Block a user