From 39f994538262237ad7207db93b9cedd1fef6d420 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Fri, 8 May 2026 13:00:49 -0400 Subject: [PATCH] Run-ShopfloorSetup: PPKG handoff + pre-PPKG network gate Block run-enrollment when this PC has no WiFi adapter and no default route. PXE imaging LAN has no DHCP gateway, so towers without WiFi get stuck in PPKG enrollment (AAD + Intune endpoints unreachable) and require a re-image. Recurring failure mode observed 2026-05-05. Tech-facing R/X retry+abort prompt walks them through plugging into a corp wall jack. Replace plain post-PPKG reboot with handoff to Monitor-IntuneProgress -PostPpkg: cancel the pending shutdown timer, run a 180s settle so MDM can push the baseline policy, render live status during settle, then issue a clean reboot. The persistent @logon sync_intune task resumes tracking on the next boot. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../shopfloor-setup/Run-ShopfloorSetup.ps1 | 73 ++++++++++++++++++- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 b/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 index 4e88b9c..c9d8986 100644 --- a/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 +++ b/playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 @@ -386,16 +386,81 @@ if (Test-Path -LiteralPath $registerMapShare) { # an immediate reboot -- everything after this call is unlikely to execute. # The sync_intune task is already registered above, so the PPKG reboot # can kill us and the chain continues on the next boot. +# ---- Network-handoff gate (BEFORE PPKG) ---- +# PXE imaging LAN has no DHCP gateway by design. Laptops with WiFi auto- +# connect to corp SSID and get a default route via WiFi - PPKG/AAD/Intune +# work fine. Towers without WiFi have ONLY the wired link to PXE LAN -> +# no default route -> AAD + Intune endpoints unreachable -> enrollment +# stalls -> re-image required (recurring failure mode observed +# 2026-05-05). Block run-enrollment until tech provides a usable internet +# path. Cheap to verify, prevents wasted imaging cycles. +$hasWifi = [bool](Get-NetAdapter -ErrorAction SilentlyContinue | + Where-Object { $_.PhysicalMediaType -eq 'Native 802.11' -or $_.MediaType -like '*802.11*' }) +$hasDefaultRoute = [bool](Get-NetRoute -DestinationPrefix '0.0.0.0/0' -ErrorAction SilentlyContinue) +if (-not $hasWifi -and -not $hasDefaultRoute) { + Write-Host "" + Write-Host "================================================================" -ForegroundColor Red + Write-Host " STOP - NO USABLE INTERNET PATH" -ForegroundColor Red + Write-Host "================================================================" -ForegroundColor Red + Write-Host "" + Write-Host " This PC has no WiFi adapter and no default route." -ForegroundColor Yellow + Write-Host " Currently on the PXE imaging LAN, which has no gateway." -ForegroundColor Yellow + Write-Host " PPKG enrollment WILL fail because AAD + Intune endpoints" -ForegroundColor Yellow + Write-Host " are unreachable from this network." -ForegroundColor Yellow + Write-Host "" + Write-Host " FIX: Plug this PC into a corp wall jack now." -ForegroundColor Cyan + Write-Host "" + Write-Host " Verify with: ipconfig" -ForegroundColor Cyan + Write-Host " A non-blank Default Gateway must show on the wired NIC." -ForegroundColor Cyan + Write-Host "" + Write-Host " Press R to retry after moving the cable." -ForegroundColor Cyan + Write-Host " Press X to abort imaging (no enrollment runs)." -ForegroundColor Cyan + Write-Host "" + while ($true) { + try { $key = ([Console]::ReadKey($true).KeyChar.ToString()).ToUpper() } + catch { $key = (Read-Host 'Press R or X').Trim().ToUpper() } + if ($key -eq 'X') { + Write-Host "Aborted by tech. Imaging stopped before PPKG." -ForegroundColor Yellow + try { Stop-Transcript | Out-Null } catch {} + exit 1 + } + if ($key -eq 'R') { + $hasDefaultRoute = [bool](Get-NetRoute -DestinationPrefix '0.0.0.0/0' -ErrorAction SilentlyContinue) + if ($hasDefaultRoute) { + Write-Host "Default route detected. Continuing to PPKG enrollment." -ForegroundColor Green + break + } + Write-Host "Still no default route. Verify cable + corp jack." -ForegroundColor Red + } + } +} + $enrollScript = Join-Path $enrollDir 'run-enrollment.ps1' if (Test-Path -LiteralPath $enrollScript) { Write-Host "" Write-Host "=== Running enrollment (PPKG install) ===" - Write-Host "NOTE: PPKG will trigger an immediate reboot. This is expected." + Write-Host "NOTE: PPKG schedules a near-immediate reboot. We will cancel" + Write-Host " it and hand off to Monitor-IntuneProgress -PostPpkg, which" + Write-Host " runs a 180s settle (giving MDM time to push baseline" + Write-Host " policy) and then performs a clean reboot." try { Stop-Transcript | Out-Null } catch {} & $enrollScript - # If we get here, the PPKG didn't reboot (maybe no PPKG file found). - Write-Host "Enrollment returned without rebooting. Rebooting now..." - shutdown /r /t 10 + + # PPKG completes -> we're back here with a pending shutdown timer. + # Hand off to Monitor in -PostPpkg mode. Monitor cancels the shutdown, + # settles, renders live status, then issues its own reboot. The + # persistent @logon sync_intune task fires on the next boot to resume + # tracking through device-category-assignment + lockdown. + Write-Host "" + Write-Host "=== Handing off to Monitor-IntuneProgress -PostPpkg ===" + cmd /c "shutdown /a 2>nul" | Out-Null + $monitor = Join-Path $setupDir 'Shopfloor\lib\Monitor-IntuneProgress.ps1' + if (Test-Path -LiteralPath $monitor) { + & powershell.exe -NoProfile -ExecutionPolicy Bypass -File $monitor -PostPpkg + } else { + Write-Warning "Monitor-IntuneProgress.ps1 not found at $monitor - falling back to plain reboot" + shutdown /r /t 10 + } } else { Write-Host "run-enrollment.ps1 not found - skipping enrollment." Write-Host ""