Files
pxe-server/playbook/shopfloor-setup/Standard/Set-MachineNumber.ps1
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

142 lines
4.9 KiB
PowerShell

# Set-MachineNumber.ps1 — Update UDC + eDNC machine number on a Standard shopfloor PC
#
# Purpose:
# Both UDC and eDNC use the same per-machine identifier ("Workstation Number" /
# "Machine Number"). On Standard PCs imaged via PXE preinstall, both are installed
# with a placeholder. When the PC is brought to its physical machine and assigned
# a real number, this helper updates both apps in one step.
#
# Persistence locations updated:
# 1. UDC: C:\ProgramData\UDC\udc_settings.json (GeneralSettings.MachineNumber)
# 2. eDNC: HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\General\MachineNo
#
# After updating, kills any running UDC.exe and relaunches it with the new args
# so the in-memory state matches the persisted value.
#
# Run as SupportUser (admin). Requires write access to ProgramData and HKLM.
Add-Type -AssemblyName Microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms
$udcSettingsPath = "C:\ProgramData\UDC\udc_settings.json"
$udcExePath = "C:\Program Files\UDC\UDC.exe"
$ednRegPath = "HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\General"
$site = "West Jefferson"
# --- Read current values for display ---
$currentUdc = $null
$currentEdnc = $null
if (Test-Path $udcSettingsPath) {
try {
$json = Get-Content $udcSettingsPath -Raw | ConvertFrom-Json
$currentUdc = $json.GeneralSettings.MachineNumber
} catch {
$currentUdc = "(unreadable: $_)"
}
}
if (Test-Path $ednRegPath) {
try {
$currentEdnc = (Get-ItemProperty -Path $ednRegPath -Name MachineNo -ErrorAction Stop).MachineNo
} catch {
$currentEdnc = $null
}
}
# --- Show prompt with current state ---
$promptLines = @()
$promptLines += "Current UDC machine number: $(if ($currentUdc) { $currentUdc } else { '(not set)' })"
$promptLines += "Current eDNC machine number: $(if ($currentEdnc) { $currentEdnc } else { '(not set)' })"
$promptLines += ""
$promptLines += "Enter the new Machine Number for this PC:"
$prompt = $promptLines -join "`n"
$new = [Microsoft.VisualBasic.Interaction]::InputBox($prompt, "Set Machine Number", "")
if ([string]::IsNullOrWhiteSpace($new)) {
Write-Host "Cancelled."
exit 0
}
$new = $new.Trim()
# --- Validate: digits only (loosen if you need alphanumerics) ---
if ($new -notmatch '^\d+$') {
[System.Windows.Forms.MessageBox]::Show(
"Machine number must be digits only.`n`nYou entered: '$new'",
"Invalid Machine Number",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Error
) | Out-Null
exit 1
}
$results = @()
# --- 1. Stop UDC.exe before editing its JSON (avoid stale shutdown write) ---
$udcProcs = Get-Process UDC -ErrorAction SilentlyContinue
if ($udcProcs) {
Write-Host "Stopping UDC.exe ($($udcProcs.Count) instance(s))..."
$udcProcs | ForEach-Object {
try {
$_.Kill()
$_.WaitForExit(5000) | Out-Null
} catch {
Write-Warning "Failed to stop UDC.exe (PID $($_.Id)): $_"
}
}
Start-Sleep -Seconds 1
}
# --- 2. Update UDC settings JSON ---
if (Test-Path $udcSettingsPath) {
try {
$json = Get-Content $udcSettingsPath -Raw | ConvertFrom-Json
$json.GeneralSettings.MachineNumber = $new
$json | ConvertTo-Json -Depth 99 | Set-Content -Path $udcSettingsPath -Encoding UTF8
Write-Host "UDC: $currentUdc -> $new"
$results += "UDC updated to $new"
} catch {
Write-Warning "Failed to update UDC settings: $_"
$results += "UDC FAILED: $_"
}
} else {
Write-Warning "UDC settings file not found at $udcSettingsPath. Run UDC.exe at least once to initialize."
$results += "UDC: settings file missing (run UDC.exe once first)"
}
# --- 3. Update eDNC MachineNo registry value ---
if (Test-Path $ednRegPath) {
try {
Set-ItemProperty -Path $ednRegPath -Name MachineNo -Value $new -Type String -Force
Write-Host "eDNC: $currentEdnc -> $new"
$results += "eDNC updated to $new"
} catch {
Write-Warning "Failed to update eDNC MachineNo: $_"
$results += "eDNC FAILED: $_"
}
} else {
Write-Warning "eDNC registry key not found at $ednRegPath. Is eDNC installed?"
$results += "eDNC: registry key missing (eDNC not installed?)"
}
# --- 4. Relaunch UDC.exe with new args (if installed) ---
if (Test-Path $udcExePath) {
try {
Start-Process -FilePath $udcExePath -ArgumentList @("-site", "`"$site`"", "-machine", $new)
Write-Host "UDC.exe relaunched."
} catch {
Write-Warning "Failed to relaunch UDC.exe: $_"
}
}
# --- 5. Show summary ---
$summary = ($results -join "`n") + "`n`nTo apply eDNC changes, restart any running DncMain.exe."
[System.Windows.Forms.MessageBox]::Show(
$summary,
"Set Machine Number — Done",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Information
) | Out-Null