Commit Graph

12 Commits

Author SHA1 Message Date
cproudlock
ac23759486 UDC firewall rules + Acrobat Reader as default PDF viewer
- Pre-create Windows Firewall inbound-allow rules for UDC.exe and
  MTConnect agent.exe before UDC_Setup.exe runs, suppressing the
  interactive "allow through firewall?" dialogs during silent install.

- Set Adobe Acrobat Reader (Acrobat.Document.DC) as the default .pdf
  handler via dism /import-defaultappassociations. Runs in
  03-ShellDefaults.ps1 so the OEMDefaultAssociations.xml is in place
  before ShopFloor's profile is created on first logon. Edge no longer
  claims .pdf on new profiles.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 09:18:44 -04:00
cproudlock
85e74e5dd1 UDC settings: pre-stage from server backups, fix arg format, action prompts
Root cause found via decompiling UDC_Setup.exe: it never writes
udc_settings.json from CLI args. Instead it pulls
Settings_Backups\udc_settings_<num>.json from \\tsgwp00525\shared\SPC\UDC
-- which is unreachable at imaging time (no SFLD creds yet). Silent
File.Exists() false, settings never copy, UDC lands on Evendale defaults.

Fix: stage 80 udc_settings_*.json backups under
shopfloor-setup/Standard/udc-backups/ (same tree as ntlars-backups,
xcopy'd to C:\Enrollment\ by existing startnet.cmd). 00-PreInstall
pre-creates C:\ProgramData\UDC\udc_settings.json from the matching
backup BEFORE UDC_Setup.exe runs. Installer's server-side copy silently
fails (unreachable), our pre-staged file survives.

Also:
- preinstall.json UDC InstallArgs corrected: "West Jefferson" -9999
  (quoted spaced site + dash-prefixed number, confirmed via decompile)
- Update-MachineNumber.ps1 UDC.exe relaunch: quoted site + dash number
- Monitor-IntuneProgress: action prompts (Select Device Category after
  Phase 1; Initiate ARTS Lockdown after Phase 5/creds), Display flow
  (3-phase: Registration -> Config -> Lockdown), Phase 6 IME-based
  lockdown detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:44:34 -04:00
cproudlock
2db35c2976 UDC: correct CLI arg signature to compact site + dash-prefixed machine#
UDC_Setup.exe and UDC.exe expect:
  UDC_Setup.exe WestJefferson -7605

Not the spaced-quoted positional pair we'd been passing:
  UDC_Setup.exe "West Jefferson" 7605

The wrong format meant UDC ignored both args, fell back to defaults
(Site=Evendale, MachineNumber=blank). Combined with the kill-after-detect
window, neither value got persisted to udc_settings.json regardless of
whether UDC.exe was given time to write.

Changes:
- preinstall.json: UDC InstallArgs now "WestJefferson -9999"
- 00-PreInstall-MachineApps.ps1: site override now matches/replaces
  the compact 'WestJefferson' token (not 'West Jefferson') and uses
  siteNameCompact from site-config; targetNum extraction regex updated
  to '-(\d+)$' for the new dash-prefix format
- Update-MachineNumber.ps1: UDC.exe relaunch now passes positional
  compact-site + dash-prefixed number instead of -site/-machine flags

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 17:47:57 -04:00
cproudlock
855af7312b Sub-type aware preinstall, USB drivers/PPKGs, Lab OpenText
- PreInstall runner reads pc-subtype.txt and matches PCTypes against
  both base type (Standard) and composite key (Standard-Machine).
- UDC scoped to Standard-Machine only. eDNC and MachineNumberACLs
  skip on Standard-Timeclock sub-type.
- Lab added to OpenText PCTypes.
- build-usb.sh copies enrollment/ (PPKGs) and drivers-staging/ (Dell
  driver packs) onto USB for self-contained deployment.
- Playbook deploys PPKGs and drivers from USB to PXE server shares.
- Gitignore enrollment/, drivers-staging/, *.ppkg (large binaries).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:00:23 -04:00
cproudlock
bc123c1066 Machine number input at PXE menu for Standard PCs
Adds a machine number prompt to startnet.cmd after the Standard sub-type
selection. Tech enters the number during the PXE boot process. Defaults
to 9999 if Enter is pressed (existing placeholder behavior).

Written to C:\Enrollment\machine-number.txt alongside pc-type.txt.

Consumers:
  00-PreInstall-MachineApps.ps1 - replaces 9999 in UDC InstallArgs with
    the entered number, so UDC installs with the correct machine number
    from the start (no post-setup Set-MachineNumber needed).
  01-eDNC.ps1 - writes the machine number to the DNC\General\MachineNo
    registry value during eDNC install.
  Configure-PC.ps1 - existing $needsMachineNumber check already skips
    the prompt when UDC/eDNC aren't at 9999, so no change needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 08:50:02 -04:00
cproudlock
7c8eb6899d Shared machine-number helper, site-config for OpenText + PreInstall, placeholder type dirs
Three optimization batches from the pipeline audit:

1. Shared Update-MachineNumber.ps1 helper (lib/)
   Extracts duplicated machine-number update logic from Configure-PC.ps1,
   Check-MachineNumber.ps1, and Set-MachineNumber.ps1 into a shared
   dot-sourceable helper at Shopfloor/lib/Update-MachineNumber.ps1.

   Exports:
     Get-CurrentMachineNumber → @{ Udc = $string; Ednc = $string }
     Update-MachineNumber -NewNumber <n> [-Site <s>] → @{ UdcUpdated; EdncUpdated; Errors }

   All three consumers now dot-source the helper instead of duplicating
   ~50 lines each. Set-MachineNumber.ps1 also migrated from inline
   Get-SiteConfig to dot-sourcing Get-PCProfile.ps1 for consistency.

2. Site-config integration for remaining scripts
   Setup-OpenText.ps1: exclude lists (profiles + shortcuts) now read from
     site-config.json opentext section, falling back to West Jefferson
     defaults. Inline Get-SiteConfig since the script runs from
     C:\PreInstall\installers\opentext\ (can't dot-source Get-PCProfile).

   00-PreInstall-MachineApps.ps1: after parsing preinstall.json, scans
     InstallArgs for "West Jefferson" and replaces with site-config
     siteName if different. Inline Get-SiteConfig for same reason.

3. Placeholder type-specific directories
   Created skeleton 01-Setup-*.ps1 scripts for all PC types so the
   directory structure is in place and Run-ShopfloorSetup's type-specific
   loop has something to iterate over:
     Genspect/01-Setup-Genspect.ps1
     Keyence/01-Setup-Keyence.ps1
     WaxAndTrace/01-Setup-WaxAndTrace.ps1
     Lab/01-Setup-Lab.ps1
   Each logs a "no type-specific apps configured yet" banner and exits.
   Fill in app installs when details are finalized; for share-based
   installs, copy the CMM/01-Setup-CMM.ps1 pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:44:10 -04:00
cproudlock
e17b3a521d Fix 5 bugs from shopfloor-setup transcript review
1. UDC JSON ACL: set on directory C:\ProgramData\UDC\ with
   ContainerInherit+ObjectInherit instead of the file. UDC_Setup.exe
   gets killed by KillAfterDetection before UDC.exe creates
   udc_settings.json, so the file doesn't exist at ACL-grant time.
   Directory-level ACL with inheritance covers any file created later.

2. Set-MachineNumber.ps1 auto-running: the type-specific loop's
   Get-ChildItem -Filter "*.ps1" picked up the desktop tool alongside
   the numbered installer scripts. Added Where-Object { $_.Name -match
   '^\d' } so only numbered-prefix scripts (01-eDNC, 02-ACLs) run.

3. WJ Shopfloor copy-to-self: Phase 1 sweep moved WJ Shopfloor.lnk
   into Shopfloor Tools\, then Phase 2's Find-ExistingLnk found it
   there and tried to Copy-Item to the same path. Now checks if
   resolved source path == destination and prints "exists: (already
   in Shopfloor Tools)" instead of erroring.

4. NTLARS missing from taskbar pins: the $pinSpec entry was never
   added to 07-TaskbarLayout.ps1 despite the comment update. Added
   between eDNC and Defect_Tracker in pin order.

5. shutdown /a stderr noise: 15+ red "Unable to abort system shutdown"
   lines in the transcript from shutdown.exe writing to stderr when no
   shutdown is pending. Changed all occurrences in Run-ShopfloorSetup,
   00-PreInstall-MachineApps to: cmd /c "shutdown /a 2>nul" *>$null
   which suppresses both native stderr and PS error stream.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 09:28:25 -04:00
cproudlock
cd00d6d2e1 OpenText: track Setup-OpenText scripts in repo, opt-in KillAfterDetection
Two related fixes from a debugging round on the test PC:

1. PreInstall runner: detection-during-install kill is now opt-in via
   "KillAfterDetection: true" on JSON entries that need it. Old behavior
   killed any installer as soon as its detection passed - which broke
   Oracle: Oracle creates its registry key partway through install,
   the runner detected it at the 25s poll, killed msiexec mid-install,
   and msiserver was still doing rollback when the next install (VC++
   2008) started - so VC++ 2008 hit ERROR_INSTALL_ALREADY_RUNNING
   (1618). Only UDC needs the detection-kill (its installer spawns a
   hidden WPF window and never exits). Other installers exit cleanly
   on their own and shouldn't be killed.

2. Track Setup-OpenText scripts in git. The bundled OpenText install
   scripts (Setup-OpenText.ps1, Setup-OpenText.cmd, version.txt) live
   at runtime in /home/camp/pxe-images/main/dependencies/opentext/
   alongside the binary install files (~106 MB of MSI/CAB/MSP/MST plus
   profile content). The binaries stay outside git but the script
   logic and version stamp are mirrored into playbook/preinstall/
   opentext/ here so git history captures changes to the install
   logic and version bumps. README.md explains the workflow.

   Latest Setup-OpenText.ps1 includes:
     - $SourceDir default moved into script body (PowerShell evaluates
       param([string]$X = $PSScriptRoot) defaults at parameter-binding
       time, when $PSScriptRoot may not yet be populated, so the
       default came out as empty string and Join-Path crashed)
     - Logging set up FIRST so any startup error gets captured
     - REBOOT=ReallySuppress dropped from both msiexec calls (base MSI
       and SP1 patch) - OpenText installs shell extensions that hook
       explorer.exe, and Restart Manager closes explorer to replace
       the shell DLLs. With REBOOT=ReallySuppress, RM closed explorer
       but interpreted the relaunch as a "reboot action" and refused
       to do it, leaving the user with no desktop. /norestart on its
       own prevents the actual Windows reboot but lets RM cleanly
       close-and-relaunch explorer mid-install.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 12:08:07 -04:00
cproudlock
5eacd1d596 PreInstall runner: surface installer log on EXE failures (LogFile field)
When the runner runs a Type:MSI install it injects /L*v <log> and tails
that log on failure to show what actually went wrong. Type:EXE installs
had no equivalent - if Setup-OpenText.cmd or any other EXE wrapper
failed, the installlog just showed "Exit code 1 - FAILED" with no clue
what happened inside.

Adds an optional LogFile field to JSON entries. When present on a
Type:EXE entry, the runner:
  - Logs "Installer log: <path>" before launching the installer
  - On failure, tails the last 30 lines of that file into the runner
    log (same pattern as the MSI verbose log scan)

Wired up on the OpenText entry to point at C:\Logs\PreInstall\Setup-
OpenText.log (which Setup-OpenText.ps1 already writes itself). Other
EXE entries can opt in by adding their own LogFile field.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:19:45 -04:00
cproudlock
564f14ffcf PreInstall runner: capture real exit codes, surface MSI errors
Three observability fixes that made the VC++ MSI failures actually
debuggable instead of showing "Exit code  - FAILED" with an empty
value for every install:

1. Switch from Start-Process -PassThru (without -Wait) to
   [System.Diagnostics.Process]::Start() with a ProcessStartInfo.
   PowerShell 5.1 has a known bug where Start-Process disposes the
   Process object's OS handle when control returns to the script,
   so $proc.ExitCode reads as $null even after WaitForExit() - which
   was causing every MSI install to be reported as failed regardless
   of the actual result.

2. Pass /L*v <log> to msiexec on every MSI install so we get a full
   verbose log per app at C:\Logs\PreInstall\msi-<safename>.log.

3. On install failure, scan the verbose log for *meaningful* lines
   (Note: 1: <code>, "return value 3", custom action errors, "Failed
   to", "Installation failed", common 2xxx error codes) instead of
   tailing the last 25 lines, which is rollback/cleanup noise. This
   surfaces the actual root-cause line directly in the runner log so
   you don't have to dig through C:\Logs to diagnose.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 10:08:42 -04:00
cproudlock
ded0a7184b Shopfloor scripts: em-dash to hyphen, add positional Level param
Replace em-dash characters with plain hyphens across the 5 shopfloor
setup scripts (avoids cp1252 mojibake in .bat files and keeps the
PowerShell sources consistent). Also adds [Parameter(Position=1)] to
Write-PreInstallLog so the Level argument can be passed positionally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 14:24:37 -04:00
cproudlock
a1a78e2ba3 PXE preinstall pipeline + Set-MachineNumber helper for Standard PCs
Adds a local-install pipeline so Standard shopfloor PCs get Oracle, the
VC++ redists (2008-2022), and UDC installed during PXE imaging via Samba
instead of pulling ~215 MB per device from Azure blob over the corporate
WAN. Intune DSC then verifies (already-installed apps are skipped) and
the only Azure traffic on the happy path is ~11 KB of CustomScripts
wrapper polling.

New files:
- playbook/preinstall/preinstall.json — curated app list with PCTypes
  filter and per-app detection rules. Install order puts VC++ 2008
  LAST so its (formerly) reboot-triggering bootstrapper doesn't kill
  the runner mid-loop. (2008 itself now uses extracted vc_red.msi with
  REBOOT=ReallySuppress; the reorder is defense in depth.)
- playbook/shopfloor-setup/Shopfloor/00-PreInstall-MachineApps.ps1 —
  the runner. Numbered 00- so it runs first in the baseline sequence.
  Reads preinstall.json, filters by PCTYPE, polls for completion via
  detection check (handles UDC's hung WPF process by killing it once
  detection passes), uses synchronous WriteThrough logging that
  survives hard reboots, preserves log history across runs.
- playbook/shopfloor-setup/Standard/Set-MachineNumber.{ps1,bat} — desktop
  helper for SupportUser. Reads current UDC + eDNC machine numbers,
  prompts via VB InputBox, validates digits-only, kills running UDC,
  edits both C:\ProgramData\UDC\udc_settings.json and HKLM\…\GE Aircraft
  Engines\DNC\General\MachineNo, relaunches UDC. Lets a tech assign a
  real machine number to a mass-produced PC without admin/LAPS.
- playbook/sync-preinstall.sh — workstation helper to push installer
  binaries from /home/camp/pxe-images/main/ to the live PXE Samba.

Changes:
- playbook/startnet.cmd + startnet-template.cmd — add xcopy to stage
  preinstall bundle from Y:\preinstall\ to W:\PreInstall\ during the
  WinPE imaging phase, gated on PCTYPE being set.
- playbook/pxe_server_setup.yml — create /srv/samba/enrollment/preinstall
  + installers/ directories and deploy preinstall.json there.
- playbook/shopfloor-setup/Run-ShopfloorSetup.ps1 — bump AutoLogonCount
  to 99 at start (defense against any installer triggering an immediate
  reboot mid-dispatcher; final line still resets to 2 on successful
  completion). Copy Set-MachineNumber.{ps1,bat} to SupportUser desktop
  on Standard PCs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 14:06:26 -04:00