12 Commits

Author SHA1 Message Date
cproudlock
2ab6055125 Fix ShopFloor autologon persistence, S: drive mapping, sync throttle
AutoLogonCount depletion:
  Run-ShopfloorSetup set AutoLogonCount=4 for SupportUser. Windows
  decrements per-logon; at 0 it clears AutoAdminLogon + DefaultPassword,
  nuking the lockdown-configured ShopFloor autologon. Fix: delete
  AutoLogonCount in Invoke-SetupComplete before the lockdown reboot.
  ShopFloor's Autologon.exe-set config persists indefinitely.

Sync_intune window on ShopFloor:
  The marker-check path used 'exit 0' but the task runs with -NoExit,
  leaving a dangling PowerShell window on every ShopFloor logon. Fix:
  [Environment]::Exit(0) kills the host outright, defeating -NoExit.

S: drive mapping:
  Vendor ConsumeCredentials.ps1 calls New-StoredCredential -Persist
  LocalMachine (needs admin) before net use. ShopFloor is non-admin so
  cred-store fails silently and net use has no auth. Fix: new
  Map-SfldShare.ps1 reads HKLM creds and passes them inline to
  net use /user: -- no Credential Manager needed, works as Limited.
  Register-MapSfldShare updated to stage + reference our script.

Wired NIC re-enable:
  SYSTEM task polls for SFLD creds (Phase 5), re-enables wired NICs,
  self-deletes. Replaces the broken Enable-NetAdapter in Monitor
  (Limited principal can't enable NICs). No-WiFi devices unaffected
  (migrate-to-wifi never disables, re-enable is a no-op).

Sync throttle:
  15 min retrigger when only waiting for lockdown (was 5 min for all
  phases). Avoids interrupting the Intune Remediation script.

Defect Tracker path:
  All references corrected to C:\Program Files (x86)\WJF_Defect_Tracker.

QR code retry:
  Build-QRCodeText retried every poll cycle until DeviceId appears
  (was single-shot that could miss the dsregcmd timing window).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:29:02 -04:00
cproudlock
f73f999938 Unified Common-Enforce for cross-type apps, add WJF Defect Tracker
Replaces the Acrobat-only enforcer with a generic Common-Enforce that
handles all cross-PC-type apps from one manifest + one scheduled task
on the SFLD share at \\tsgwp00525\shared\dt\shopfloor\common\apps\.

Renames:
  Acrobat-Enforce.ps1        -> Common-Enforce.ps1
  Register-AcrobatEnforce    -> Register-CommonEnforce
  acrobat-manifest.json      -> common-apps-manifest.json
  common.acrobatSharePath    -> common.commonAppsSharePath
  'GE Acrobat Enforce' task  -> 'GE Common Apps Enforce' task
  C:\Program Files\GE\Acrobat -> C:\Program Files\GE\CommonApps

Register-CommonEnforce cleans up the legacy 'GE Acrobat Enforce' task
if present from a prior image.

WJF Defect Tracker (replaces ClickOnce):
  - Added to preinstall.json (PCTypes=*, fleet-wide imaging-time install)
  - MSI staged on PXE at pre-install/installers/
  - Added to common-apps-manifest with FileVersion detection on
    C:\Program Files\WJF_Defect_Tracker\Defect_Tracker.exe
  - site-config + 06-OrganizeDesktop: shortcut changed from ClickOnce
    'existing' to exe-path pointing at the MSI-installed binary
  - Update workflow: drop new MSI on share, bump DetectionValue

CMM 09-Setup-CMM: added goCMM + DODA to the ACL grant list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:13:05 -04:00
cproudlock
6db170bf54 Shell defaults + eDNC reg restore from machine-number backups
- 03-ShellDefaults.ps1: Default-User TaskbarAl=0 (left), HKLM policies to
  hide Start Recommended section, kill Bing web search + suggestions,
  disable Cortana. LTSC-honoured; runs fleet-wide via baseline loop.

- ntlars-backups/: 147 per-machine eDNC registry backups renamed to
  flat <MachineNumber>.reg scheme. Historical off-by-one entries from
  the original dump rewritten to match CSV-target MachineNo.

- Standard/03-RestoreEDncConfig.ps1: at imaging time, if tech typed a
  real machine number at PXE (not 9999), import <num>.reg from the local
  staged copy. Restores eFocas IP, PPDCS serial, Hssb relays -- not just
  the bare MachineNo. Skipped on Timeclock / 9999 / missing backup.

- Update-MachineNumber.ps1: when tech later sets a real number from 9999,
  pull <num>.reg from tsgwp00525 SFLD share (ntlarsBackupSharePath in
  site-config) and reg-import it before writing the new MachineNo.

- Restore-EDncReg.ps1: shared helper (Mount-SFLDShare + Import-EDncRegBackup)
  used by both callers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:42:21 -04:00
cproudlock
3ef981f19e Add Standard-Machine logon enforcer for UDC/eDNC/NTLARS
Reason: Intune DSC's main-category YAML was pushing these to every main
device, including Timeclocks - DSC has no awareness of our pc-subtype
distinction. After UDC/eDNC/NTLARS are removed from the DSC YAML, ongoing
version drift would no longer be corrected. This enforcer replaces that,
scoped correctly by subtype.

Structure mirrors CMM (CMM-Enforce.ps1) and common (Acrobat-Enforce.ps1):
- Machine-Enforce.ps1: SYSTEM logon task; mounts SFLD share with HKLM-
  backed creds; hands off to Install-FromManifest.
- machineapps-manifest.template.json: repo reference; authoritative copy
  lives on the share at \\tsgwp00525.wjs.geaerospace.net\shared\dt\
  shopfloor\main\machineapps\machineapps-manifest.json.
- Register-MachineEnforce.ps1: idempotent setup; stages scripts to
  C:\Program Files\GE\MachineApps and registers the task.
- lib/Install-FromManifest.ps1: copy of the common/ version (already has
  Type=CMD support).

Sub-type gating belt-and-suspenders:
- Run-ShopfloorSetup.ps1 only calls Register-MachineEnforce when
  $pcType -eq "Standard" -and $pcSubType -eq "Machine".
- Machine-Enforce.ps1 itself re-reads pc-subtype.txt and exits early if
  not "Machine", so a mistakenly-deployed copy no-ops.

site-config.json:
- Added "machineappsSharePath" to Standard-Machine pcProfile.

Drive letter U: to stay clear of CMM (S:) and Acrobat (T:) enforcers
that may run concurrently at logon.

Update workflow:
  drop new UDC/eDNC/NTLARS installer on the SFLD share,
  bump DetectionValue in machineapps-manifest.json,
  every Machine PC catches up on next user logon.
2026-04-15 12:16:17 -04:00
cproudlock
8848fca88a Add Acrobat Reader logon enforcer (cross-PC-type), provtool.exe arg fix
Acrobat Reader enforcement:
- playbook/shopfloor-setup/common/ is the cross-PC-type staging dir. Mirrors
  CMM/ structure (enforce script + its Install-FromManifest copy + manifest
  template + register script).
- Acrobat-Enforce.ps1 runs as SYSTEM on every logon, reads
  acrobatSharePath from site-config.common, mounts the SFLD share with
  the same HKLM-backed credential lookup CMM-Enforce uses, hands the
  acrobat-manifest.json from the share to Install-FromManifest.
- Install-FromManifest extended with Type=CMD so it can invoke vendor-
  supplied .cmd wrappers (Install-AcroReader.cmd does a two-step MSI+MSP
  install that does not fit MSI/EXE types cleanly). cmd.exe /c wraps it
  because UseShellExecute=false cannot launch .cmd directly.
- Register-AcrobatEnforce.ps1 stages scripts to C:\Program Files\GE\Acrobat
  and registers "GE Acrobat Enforce" scheduled task. Called from
  Run-ShopfloorSetup.ps1 right before the enrollment (PPKG) step so it
  applies to every PC type, not just CMM.
- acrobat-manifest.template.json is the repo reference; the authoritative
  copy lives on the SFLD share at
  \\tsgwp00525.wjs.geaerospace.net\shared\dt\shopfloor\common\acrobat\
  Bumping Acrobat updates = drop new MSP on share, bump DetectionValue in
  manifest; enforcer catches every PC on next logon.
- site-config.json: add "common": { "acrobatSharePath": ... }. Uses a
  new top-level block rather than a PC-type-specific one since Acrobat
  applies everywhere.

Initial install still happens via the preinstall flow
(Install-AcroReader.cmd during WinPE). The enforcer is the ongoing-
updates side; on a freshly-imaged PC detection passes and it no-ops.

Also in this commit:
- run-enrollment.ps1: provtool.exe argument syntax fix. First test
  returned 0x80004005 E_FAIL in 1s because /ppkg: and /log: are not
  valid provtool flags; the cmdlet's internal call used positional
  path + /quiet + /source. Switched to that syntax.
2026-04-15 09:24:13 -04:00
cproudlock
f3211dfd29 CMM test iteration: desktop shortcuts, rename to 09-Setup-*, defer NIC re-enable
Rolls up everything from the CMM imaging test iteration tonight. No
single concern - several small, related polish items on the option-3
patched-MSI pipeline and the shopfloor-setup / sync_intune handoff.

- Rename all type-specific "01-Setup-<Type>.ps1" scripts to
  "09-Setup-<Type>.ps1" across CMM, Display, Genspect, Keyence, Lab,
  and WaxAndTrace. The "01-" prefix implied the script runs first in
  the overall sequence when it actually runs between baseline (00, 04)
  and finalization (06, 07). Logs now read "Running CMM setup:
  09-Setup-CMM.ps1" which matches the real position. Standard/
  01-eDNC.ps1 + 02-MachineNumberACLs.ps1 left alone - those digits
  represent real within-type ordering.
- playbook/shopfloor-setup/site-config.json CMM profile updates:
  - startupItems = [] (empty). Previously had WJ Shopfloor auto-launch
    which the user does not want on CMM workstations. Now relies on
    the Get-ProfileValue empty-array fix to not fall through to site
    defaults.
  - desktopApps + taskbarPins gain entries for PC-DMIS 2016, PC-DMIS
    2019 R2, CLM Admin, and goCMM so 06-OrganizeDesktop Phase 2
    materializes them into C:\\Users\\Public\\Desktop\\Shopfloor Tools\\
    and 07-TaskbarLayout pins them. goCMM is under C:\\Program Files
    (x86)\\General Electric\\goCMM\\ (GE product, not Hexagon).
- playbook/shopfloor-setup/Run-ShopfloorSetup.ps1: remove the blocking
  "UNPLUG ethernet cable, press any key" prompt + the interactive
  wired-NIC re-enable. The whole prompt block was a hard blocker on
  the imaging chain that required a human to walk to each PC.
- playbook/shopfloor-setup/Shopfloor/lib/Monitor-IntuneProgress.ps1:
  re-enable wired NICs unconditionally at the top of the transcript.
  This is the new home for the re-enable that used to live behind the
  prompt in Run-ShopfloorSetup. By the time sync_intune fires (after
  PPKG reboot + auto-login + Stage-Dispatcher), the tech has had
  minutes of wall-clock time to physically rewire from PXE to
  production without us blocking on a keypress. Tower case is a
  no-op because migrate-to-wifi.ps1 already left wired enabled.
- Internal comment updates in 09-Setup-CMM.ps1, cmm-manifest.json,
  Install-FromManifest.ps1, and startnet.cmd (+ startnet-template)
  to reflect the new filename.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:03:09 -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
ed3bfc8234 Lab Workstation: profile-aware Edge homepage + startup tabs
Lab profile in site-config.json now has:
  edgeHomepage: http://tsgwp00524.logon.ds.ge.com/
  edgeStartupTabs: WJ Shop Floor Homepage, M365 Webmail, Shopfloor Dashboard

08-EdgeDefaultBrowser.ps1 now resolves edge config from:
  pcProfile.edgeStartupTabs > siteConfig.edgeStartupTabs > hardcoded
  pcProfile.edgeHomepage > first startup tab (existing behavior)

This lets different PC types have different Edge configs:
  Standard-Machine: Plant Apps + Homepage + Dashboard (homepage = Plant Apps)
  Lab: Homepage + Webmail + Dashboard (homepage = tsgwp00524)

Added webmail URL to site-config.json urls section:
  "webmail": "https://outlook.office365.us/mail"

Lab gets no OpenText/UDC/eDNC — already filtered:
  OpenText + UDC: PCTypes = ["Standard"] in preinstall.json
  eDNC: Standard/01-eDNC.ps1 (type-specific, never runs for Lab)
  Office: from PPKG (shared across all shopfloor types)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:49:43 -04:00
cproudlock
b236b18fbc CMM: share-based installer framework with SFLD credential lookup
Refactored CMM/01-Setup-CMM.ps1 from local-file installer to network-
share-based pattern. CMM apps live on a file share instead of being
pre-staged locally or pulled from Azure Blob.

Framework:
  1. Reads share path from site-config.json CMM profile (cmmSharePath),
     falls back to West Jefferson default
  2. Scans HKLM:\SOFTWARE\GE\SFLD\Credentials\* for a credential entry
     whose TargetHost matches the share's server name
  3. Mounts the share as S: using net use with the stored creds
  4. (Placeholder) Install apps from the share
  5. Disconnects the share

The Get-SFLDCredential helper function is generic and will be reused by
Genspect/Keyence scripts when their share-based installs are built. It
matches credentials by TargetHost field, supporting exact match and
domain-suffix matching.

App install blocks are commented out as placeholders — uncomment when
PC-DMIS, CLM License, and other Hexagon app details are finalized.

Added cmmSharePath to site-config.json CMM profile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:24:22 -04:00
cproudlock
ed803539e0 PC profiles: per-type/sub-type config + Standard Timeclock/Machine menu
Adds a pcProfiles section to site-config.json that lets each PC type (and
optional sub-type) override startupItems, taskbarPins, and desktopApps.
Scripts resolve: pcProfile > site-wide default > hardcoded fallback.

New shared helper: Shopfloor/lib/Get-PCProfile.ps1
  Dot-sourced by consuming scripts. Reads pc-type.txt + pc-subtype.txt,
  builds a profile key (e.g. "Standard-Machine"), and looks it up in
  site-config.json pcProfiles. Exports $siteConfig, $pcType, $pcSubtype,
  $profileKey, $pcProfile for the caller to use.

  Replaces the inline Get-SiteConfig function that was copy-pasted into
  each script. Scripts now do:
    . "$PSScriptRoot\lib\Get-PCProfile.ps1"
  instead of duplicating the loader.

startnet.cmd changes:
  - Added Lab as PC type option (7)
  - Standard now has a sub-type menu: Timeclock / Machine
  - Display sub-type menu also writes PCSUBTYPE for consistency
  - pc-subtype.txt written alongside pc-type.txt when sub-type selected
  - site-config.json copied from enrollment share to W:\Enrollment\

site-config.json v2.0:
  - New pcProfiles section with profiles for:
    Standard-Timeclock, Standard-Machine, CMM, Genspect, Keyence,
    WaxAndTrace, Lab, Display-Lobby, Display-Dashboard
  - CMM/Genspect/Keyence/WaxAndTrace profiles have TODO comments for
    type-specific apps (placeholder with WJ Shopfloor baseline only)
  - Lab/Display profiles have empty startupItems and desktopApps
  - Top-level startupItems/taskbarPins/desktopApps remain as site-wide
    defaults (used when no profile matches)

Updated scripts:
  06-OrganizeDesktop.ps1 - desktopApps from profile > site > hardcoded
  07-TaskbarLayout.ps1   - taskbarPins from profile > site > hardcoded
  08-EdgeDefaultBrowser.ps1 - uses shared profile loader
  Configure-PC.ps1       - startupItems from profile > site > hardcoded

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:19:51 -04:00
cproudlock
0aaf049942 Extract site-specific values to site-config.json
New site-config.json file at C:\Enrollment\ (staged by startnet.cmd from
the enrollment share) contains all West Jefferson-specific values that were
previously hardcoded across 7 scripts. To deploy at a different GE site,
clone site-config.json and change the values - scripts need zero changes.

Config schema (v1.0):
  siteName / siteNameCompact  - UDC/eDNC site args
  urls{}                      - Edge startup tab fallback URLs
  edgeStartupTabs[]           - ordered tab list with .url file basenames
  opentext{}                  - excluded .hep profiles and .lnk shortcuts
  startupItems[]              - Configure-PC toggle list (exe/existing/url)
  taskbarPins[]               - 07-TaskbarLayout pin order with lnk paths
  desktopApps[]               - 06-OrganizeDesktop Phase 2 app list

Every script uses the same inline Get-SiteConfig helper that reads the
JSON and returns $null if missing/corrupt. All consumers fall back to the
current hardcoded West Jefferson defaults when $siteConfig is null, so
PXE servers without a site-config.json continue working identically.

Scripts updated:
  06-OrganizeDesktop.ps1   - desktopApps array from config
  07-TaskbarLayout.ps1     - pinSpec array from config
  08-EdgeDefaultBrowser.ps1 - startup tab loop from config
  Configure-PC.ps1         - startup items + site name from config
  Check-MachineNumber.ps1  - site name from config
  Set-MachineNumber.ps1    - site name from config
  01-eDNC.ps1              - siteName + siteNameCompact from config
  startnet.cmd             - copies site-config.json from enrollment share

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:11:35 -04:00