Shopfloor sync_intune + Set-MachineNumber hardening

Long debugging round on the shopfloor test PC with several overlapping
bugs. This commit folds all the fixes together.

sync_intune.bat
- Slim down to an elevation thunk that launches a NEW elevated PS
  window via Start-Process -Verb RunAs (with -NoExit so the window
  doesn't vanish on error). All UI now lives in the PS monitor, not
  mixed into the cmd launcher.
- Goto-based control flow. Earlier version had nested if (...) blocks
  with literal parens inside echo lines (e.g. "wrappers (Install-eDNC,
  ...etc)."); cmd parses if-blocks by counting parens character-by-
  character, so the ")" in "etc)." closed the outer block early and
  the leftover "." threw ". was unexpected at this time.", crashing
  the elevated cmd /c window before pause ran.
- Multi-location Monitor-IntuneProgress.ps1 lookup so the user's
  quick-test workflow (drop both files on the desktop) works without
  manually editing the hardcoded path. Lookup order:
    1. %~dp0lib\Monitor-IntuneProgress.ps1
    2. %~dp0Monitor-IntuneProgress.ps1
    3. C:\Users\SupportUser\Desktop\Monitor-IntuneProgress.ps1
    4. C:\Enrollment\shopfloor-setup\Shopfloor\lib\Monitor-IntuneProgress.ps1
- Prints "Launching: <path>" as its first line so you can see which
  copy it actually loaded. This caught a bug where a stale desktop
  copy was shadowing the canonical file via fallback #2.

Set-MachineNumber.bat
- Same multi-location lookup pattern. Old version used
  %~dp0Set-MachineNumber.ps1 and bombed when the bat was copied to
  the desktop without its .ps1 sibling.
- Goto-based dispatch, no nested parens, for the same parser reason.

Monitor-IntuneProgress.ps1
- Start-Transcript at the top, writing to C:\Logs\SFLD\ (falls back
  to %TEMP% if C:\Logs\SFLD isn't writable yet) with a startup banner
  including a timestamp. Every run leaves a captured trace.
- Main polling loop wrapped in try/catch/finally. Unhandled exceptions
  print a red report with type, message, position, and stack trace,
  then block on Wait-ForAnyKey so the window can't auto-close on a
  silent crash.
- Console window resize at startup via $Host.UI.RawUI.WindowSize /
  BufferSize, wrapped in try/catch (Windows Terminal ignores it, but
  classic conhost honors it).
- Clear-KeyBuffer / Read-SingleKey / Wait-ForAnyKey helpers. Drain any
  buffered keystrokes from the polling loop before each prompt so an
  accidental keypress can't satisfy a pause prematurely.
- Invoke-SetupComplete / Invoke-RebootPrompt final-state handlers.
  The REBOOT REQUIRED branch now shows a yellow 3-line header, a
  four-line explanation, and a cyan "Press Y to reboot now, or N to
  cancel:" prompt via Read-SingleKey @('Y','N'). Y triggers
  Restart-Computer -Force (with shutdown.exe fallback), N falls
  through to Wait-ForAnyKey.
- Display order: status table FIRST, QR LAST. The cursor ends below
  the QR so the viewport always follows it - keeps the QR on screen
  regardless of window height. Works on both classic conhost and
  Windows Terminal (neither reliably honors programmatic resize).
- Half-block QR renderer: walks QRCoder's ModuleMatrix directly and
  emits U+2580 / U+2584 / U+2588 / space, one output line per two
  matrix rows. Halves the rendered height vs AsciiQRCode full-block.
  Quiet zone added manually via $pad=4 since QRCoder's ModuleMatrix
  doesn't include one. Trade-off: may not be perfectly square on all
  fonts, but the user accepted that for the smaller footprint after
  multiple iterations comparing full-block vs half-block vs PNG popup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-04-09 13:30:12 -04:00
parent cd00d6d2e1
commit c464f45f4f
3 changed files with 336 additions and 121 deletions

View File

@@ -1,6 +1,38 @@
@echo off
REM Set-MachineNumber.bat - Wrapper for Set-MachineNumber.ps1
REM Runs the PowerShell helper with bypass execution policy so a double-click
REM from the desktop just works.
REM
REM Looks for the .ps1 in three places, in order:
REM 1. %~dp0Set-MachineNumber.ps1
REM - .bat and .ps1 side-by-side (normal desktop-copied case, repo layout)
REM 2. C:\Users\SupportUser\Desktop\Set-MachineNumber.ps1
REM - dispatcher-copied location, if this .bat lives somewhere else
REM 3. C:\Enrollment\shopfloor-setup\Standard\Set-MachineNumber.ps1
REM - canonical enrollment staging copy
REM
REM Goto-based dispatch - no nested if blocks, no literal parens in echo lines.
REM CMD parses "if (...)" blocks by counting parens and will silently eat any
REM "(" or ")" inside an echo, so keeping the flow flat avoids that class of
REM syntax bomb entirely.
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0Set-MachineNumber.ps1"
setlocal
set "PS1=%~dp0Set-MachineNumber.ps1"
if exist "%PS1%" goto :run
set "PS1=C:\Users\SupportUser\Desktop\Set-MachineNumber.ps1"
if exist "%PS1%" goto :run
set "PS1=C:\Enrollment\shopfloor-setup\Standard\Set-MachineNumber.ps1"
if exist "%PS1%" goto :run
echo ERROR: Set-MachineNumber.ps1 not found in any of:
echo %~dp0Set-MachineNumber.ps1
echo C:\Users\SupportUser\Desktop\Set-MachineNumber.ps1
echo C:\Enrollment\shopfloor-setup\Standard\Set-MachineNumber.ps1
echo.
pause
exit /b 1
:run
echo Launching: %PS1%
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%PS1%"
exit /b %errorlevel%