Commit Graph

14 Commits

Author SHA1 Message Date
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
743bc91996 Shopfloor Display: move kiosk app install to preinstall system
Install-KioskApp.cmd wrapper reads display-type.txt and runs the
matching Inno Setup installer (Lobby or Dashboard). Replaces the
standalone 09-Setup-Display.ps1 for uniform app install pipeline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:38:59 -04:00
cproudlock
8455c80aa4 Shopfloor preinstall: add Adobe Acrobat Reader DC for all PC types
Same version as GEA-Engineering image. Two-step install via wrapper
script (MSI + enterprise transform, then DC update patch).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 07:51:21 -04:00
cproudlock
b88e4d3272 CMM: patched-MSI install chain for PC-DMIS 2016 + 2019 R2
PC-DMIS refuses to install without a valid license in /qn mode; its
BA / MSI custom actions ProcessLicensingFromBundle (which spins for
~13 minutes trying to activate against licensing.wilcoxassoc.com)
and IsLicenseDateValid (which errors 1603 when no license file is
present) are the gate. Bypassed by dark-extracting the chained MSIs
from each Burn bundle and pre-patching both custom actions'
InstallExecuteSequence.Condition columns to '0' via Windows
Installer COM SQL UPDATE. The patched MSIs install cleanly with no
license, PCDLRN.exe loads at runtime, hits its own runtime license
check, and shows the normal "no license" dialog. Tech activates via
clmadmin.exe post-imaging and PC-DMIS launches normally.

- playbook/preinstall/preinstall.json: adds VC++ 2010 x64 and VC++
  2012 x64 redistributable entries scoped to all PC types. PC-DMIS
  links msvcr100.dll / mfc100u.dll (VS 2010) and msvcr110.dll /
  mfc110u.dll (VS 2012); without these the exe gets DLL_NOT_FOUND
  (0xC0000135) at launch. Win11 ships VC++ 2022 (covers 2015+) but
  not 2010/2012, so we ship these from the dark-extracted bundle
  payloads. Small (~13 MB combined), inert on PCs that don't need
  them, so the filter is "*".
- playbook/shopfloor-setup/CMM/cmm-manifest.json: version 2.0.
  Drops the bundle EXEs, installs patched MSIs directly with
  properly quoted INSTALLFOLDER / APPLICATIONFOLDER paths (the
  earlier "hangs" were caused by Start-Process splitting unquoted
  paths on spaces, not actual msiexec hangs). Skips the chained
  CLM Tools 1.5/1.7 MSIs - CLM 1.8.73 standalone provides the same
  interfaces and PC-DMIS MSIs have no LaunchCondition requiring
  Tools 1.5 / 1.7 specifically. Keeps Protect Viewer from the 2019
  R2 bundle as a separate entry. CLM 1.8 and goCMM bundles run
  unpatched (no install-time license check).
- playbook/sync-cmm.sh: now also includes *.msi files in the
  upload set, not just *.exe.

Known caveats: patched MSIs have HashMismatch signatures (expected
- Windows Installer accepts them in /qn mode on locally-cached
  machines). Every Hexagon bundle version bump requires re-dark-
extracting and re-patching. Unsupported by Hexagon; do not call
them for install-related issues without reverting to the original
bundles first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 16:52:54 -04:00
cproudlock
ee7d3bad66 Shopfloor imaging: CMM type, Configure-PC override fix, serial drivers
- CMM imaging pipeline: WinPE-staged bootstrap + on-logon enforcer
  against tsgwp00525 share, manifest-driven installer runner shared via
  Install-FromManifest.ps1. Installs PC-DMIS 2016/2019 R2, CLM 1.8,
  goCMM; enables .NET 3.5 prereq; registers GE CMM Enforce logon task
  for ongoing version enforcement.
- Shopfloor serial drivers: StarTech PCIe serial + Prolific PL2303
  USB-to-serial via Install-Drivers.cmd wrapper calling pnputil
  /add-driver /subdirs /install. Scoped to Standard PCs.
- OpenText extended to CMM/Keyence/Genspect/WaxAndTrace via
  preinstall.json PCTypes; Defect Tracker added to CMM profile
  desktopApps + taskbarPins.
- Configure-PC startup-item toggle now persists across the logon
  sweep via C:\\ProgramData\\GE\\Shopfloor\\startup-overrides.json;
  06-OrganizeDesktop Phase 3 respects suppressed items.
- Get-ProfileValue helper added to Shopfloor/lib/Get-PCProfile.ps1;
  distinguishes explicit empty array from missing key (fixes Lab
  getting Plant Apps in startup because empty array was falsy).
- 06-OrganizeDesktop gains transcript logging at C:\\Logs\\SFLD\\
  06-OrganizeDesktop.log and now deletes the stale Shopfloor Intune
  Sync task when C:\\Enrollment\\sync-complete.txt is present (task
  was registered with Limited principal and couldn't self-unregister).
- startnet.cmd CMM xcopy block (gated on pc-type=CMM) stages the
  bundle to W:\\CMM-Install during WinPE.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 12:58:47 -04:00
cproudlock
6c76719a47 Logging, PCTypes, edge profiles for all types
Three final optimization batches:

1. Start-Transcript added to 4 scripts that lacked standalone logging:
   04-NetworkAndWinRM.ps1, 05-OfficeShortcuts.ps1, 01-eDNC.ps1,
   02-MachineNumberACLs.ps1. Each writes to C:\Logs\SFLD\<name>.log
   with append mode. Stop-Transcript added before exit points.

2. preinstall.json: Oracle Client PCTypes changed from ["*"] to
   ["Standard", "CMM", "Genspect", "Keyence", "WaxAndTrace", "Display"].
   Lab Workstations don't need Oracle Client (shopfloor data app
   dependency). VC++ redists stay at ["*"] (harmless shared deps).

3. Edge profiles added to all remaining PC types in site-config.json:
   CMM, Genspect, Keyence, WaxAndTrace, Standard-Timeclock all get the
   standard 3-tab setup (Plant Apps + Homepage + Dashboard) with
   homepage = tsgwp00524. Display-Lobby and Display-Dashboard get
   Shopfloor Dashboard as both homepage and single tab.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:57:22 -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
a363fa31c0 OpenText: migrate from Intune Win32 LOB to PXE PreInstall + DSC
OpenText HostExplorer ShopFloor was previously delivered as an Intune
Win32 LOB app that ran the inner OpenTextHostExplorer15x64.msi directly,
which (a) skipped the [Files] section of the WJDT-built Inno Setup
wrapper that deploys profile/keymap/menu/macro files, and (b) deployed
desktop shortcuts pointing at C:\\GE Aerospace\\Hummingbird\\ - a path
HostExplorer doesn't search, so the profile would open from the desktop
shortcut but the keymaps and macros never got picked up.

This commit moves the install to the PXE PreInstall pipeline so it
gets baked into every Standard PC during imaging instead of being
pulled per-device by Intune. The DSC side ships separately as
Setup-OpenText.ps1 + Install-OpenText.ps1 wrapper in the
pxe-images/main/ tree (uploaded to Azure Blob).

preinstall.json: new entry for OpenText pointing at
opentext\\Setup-OpenText.cmd, a tiny launcher in the bundled subtree
that hands off to Setup-OpenText.ps1 (the runner only handles MSI/EXE
types). No DetectionMethod fields - Setup-OpenText.ps1 reads version
from version.txt next to itself and short-circuits via its own
HKLM\\SOFTWARE\\GE\\OpenText\\Installed marker check, so the version
constant lives in exactly one place (version.txt). Trade-off: ~1s
PowerShell launch on every up-to-date runner pass instead of a
zero-cost registry compare, in exchange for never having to bump
the version in multiple places.

sync-preinstall.sh: added dependencies/opentext to TREE_SUBDIRS so
the whole bundle (base MSI + cab + SP1 patch + ShopFloor transform +
profile/accessories/keymap/menu/W10shortcuts content + Setup-OpenText
script and cmd wrapper + version.txt) rides through the existing tar
pipe. Also added OpenText.exe to the legacy-cleanup rm list since the
old flat machineapps/OpenText.exe path is now obsolete.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 10:10:35 -04:00
cproudlock
b4dd8a4197 VC++ extracted MSIs: bypass LaunchCondition CA via NOVSUI=1
The extracted VC++ 2008/2010/2012/2013/2022 MSIs have a hardcoded
CustomAction CA_LaunchCondition (type 19 = msidbCustomActionTypeError)
whose Target is "To install this product, please run Setup.exe.  For
other installation options, see the Installation section of ReadMe.htm."
The CA's Condition row in InstallExecuteSequence is:

  NOT( (ADDEPLOY = 1 OR NOVSUI = 1 OR VSEXTUI = 1 OR
        ADVERTISED = 1 OR ProductState >= 1) )

So it fires (= aborts the install with that error) unless one of those
sentinel properties is set on the command line. The 2008 MSI uses a
slightly different name (CA_LaunchCondition_5122) and a different set:

  NOT( (USING_EXUIH = 1 OR USING_EXUIH_SILENT = 1 OR ProductState >= 1) )

The bootstrappers normally set NOVSUI=1 / USING_EXUIH_SILENT=1 to
identify themselves as non-interactive installers. When we run the
extracted MSI directly via msiexec, the property isn't set, the CA
fires, msiexec returns 1603 with MSI Note 1: 1708, and the install
rolls back.

Fix: pass both properties unconditionally on every VC++ install. MSIs
ignore unknown properties, so one args string works for all of them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 10:10:11 -04:00
cproudlock
61e0f3a033 Preinstall: extract MSIs for all VC++ redists to suppress reboot
The Microsoft VC++ bootstrappers (vcredist*_x86.exe) ignore /norestart
and trigger immediate Windows reboots when CRT DLLs are in use, which
in practice is always. We saw this break a live Standard PC imaging
run (installlog showed the manual shutdown -a sequence between runs).

Fix follows the existing 2008 pattern: extract the inner MSIs from
each Burn bundle, run them via msiexec with REBOOT=ReallySuppress
(a hard Windows Installer property the bootstrapper can't override),
and treat exit 3010 as success. Files are now staged per-version
under dependencies/vcredist/<version>/ because each MSI's Media table
hardcodes its CAB filename, so the pairs would otherwise collide.

preinstall.json: 4 EXE entries replaced with 8 MSI entries (Min+Add
for 2012/2013/2022 because each version's Burn bundle ships them
as separate MSIs). 2008 also moved into the same vcredist/2008/
subdir for consistency. ProductCodes verified against the existing
detection paths (the previous "bootstrapper" GUIDs were actually
the Min runtime GUIDs inherited up the chain).

sync-preinstall.sh: now tarballs the dependencies/vcredist/ subtree
to preserve directory structure across the scp+sudo-cp boundary,
flat installers (UDC, Oracle) still copied individually, and the
remote install script now removes the legacy flat vc_red.msi/cab
plus the obsolete vcredist*_x86.exe bootstrappers on every sync.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:01:23 -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