Harvest provtool diagnostics, enable ETW channel, skip Timeclock machine#

run-enrollment.ps1:
- Enable Provisioning-Diagnostics-Provider/Admin event log before invoking
  provtool (was disabled by default; no diagnostics survived early runs).
- After provtool returns, copy C:\ProgramData\Microsoft\Provisioning\*
  into C:\Logs\PPKG\ and snapshot HKLM\...\Sessions\* as
  provisioning-sessions.json, plus export the Admin event channel to
  Provisioning-Diagnostics-Admin.evtx. Gives us reviewable state
  without relying on provtool's failure-only diagnostic bundle.
- provtool arg order is positional path + /quiet + /source BPRT (verified
  against ProvEventLog from the PS cmdlet internal call).

startnet.cmd / startnet-template.cmd:
- Standard-Timeclock sub-type skips the machine-number prompt. Timeclock
  PCs do not use a machine number so forcing a prompt wasted tech time
  and left MACHINENUM at the 9999 default anyway. Machine sub-type is
  unaffected.
This commit is contained in:
cproudlock
2026-04-15 14:22:43 -04:00
parent cc9aad0ea1
commit 67845372b2
3 changed files with 73 additions and 2 deletions

View File

@@ -59,7 +59,18 @@ $provtool = Join-Path $env:SystemRoot 'System32\provtool.exe'
# internally (observed in ProvEventLog.txt): positional path, then /quiet,
# then /source. No /log: or /ppkg: prefix - those are not valid provtool
# flags and caused 0x80004005 E_FAIL in the first test.
#
# /source BPRT keeps us in the bulk-provisioning code path used by the
# automatic OOBE PPKG runtime. PSCmdlet would give richer ETW/event-log
# diagnostics, but may change which actions in the PPKG actually execute
# (not verified against Microsoft docs). Stay on BPRT and enable logging
# manually below.
$provArgs = @("`"$($ppkgFile.FullName)`"", "/quiet", "/source", "BPRT")
# Enable the Provisioning-Diagnostics-Provider Admin channel so events
# from the BPRT run land somewhere we can export afterward. This is
# idempotent - running each time is safe.
wevtutil.exe set-log 'Microsoft-Windows-Provisioning-Diagnostics-Provider/Admin' /enabled:true 2>$null | Out-Null
Log "Installing provisioning package via provtool.exe (no PowerShell timeout)..."
Log "Command: $provtool $($provArgs -join ' ')"
Log "PPKG diagnostic logs -> $ppkgLogDir (provtool writes them automatically)"
@@ -74,6 +85,64 @@ try {
Log "ERROR: Failed to launch provtool.exe: $_"
}
# --- Harvest Windows' own provisioning diagnostics into $ppkgLogDir ---
# provtool.exe /quiet does not drop a zip bundle on success, so the real
# detail lives under C:\ProgramData\Microsoft\Provisioning\, in the
# registry under HKLM\Software\Microsoft\Provisioning\Sessions\*, and in
# the Provisioning-Diagnostics-Provider event log. Copy/export all three
# into our log dir so they ride back with the shopfloor logs bundle.
Log "Harvesting Windows provisioning diagnostics to $ppkgLogDir..."
try {
$provData = 'C:\ProgramData\Microsoft\Provisioning'
if (Test-Path $provData) {
Copy-Item -Path (Join-Path $provData '*') -Destination $ppkgLogDir `
-Recurse -Force -ErrorAction SilentlyContinue
Log " copied $provData -> $ppkgLogDir"
} else {
Log " $provData not present (provtool may not have touched it)"
}
} catch {
Log " WARN: ProgramData copy threw: $_"
}
try {
$sessions = Get-ChildItem 'HKLM:\Software\Microsoft\Provisioning\Sessions' -ErrorAction SilentlyContinue
if ($sessions) {
$snap = $sessions | ForEach-Object {
$props = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue
if ($props) {
[pscustomobject]@{
Session = $_.PSChildName
BeginTime = $props.BeginTime
LastRunTime = $props.LastRunTime
RebootCount = $props.RebootCount
State = $props.State
StateValue = $props.StateValue
}
}
}
$snap | ConvertTo-Json -Depth 3 |
Out-File -FilePath (Join-Path $ppkgLogDir 'provisioning-sessions.json') -Encoding UTF8
Log " wrote provisioning-sessions.json ($($snap.Count) session(s))"
foreach ($s in $snap) {
Log " session $($s.Session): State=$($s.State) RebootCount=$($s.RebootCount)"
}
} else {
Log " no sessions under HKLM:\Software\Microsoft\Provisioning\Sessions"
}
} catch {
Log " WARN: session snapshot threw: $_"
}
try {
$evtx = Join-Path $ppkgLogDir 'Provisioning-Diagnostics-Admin.evtx'
if (Test-Path $evtx) { Remove-Item $evtx -Force -ErrorAction SilentlyContinue }
$null = & wevtutil.exe epl 'Microsoft-Windows-Provisioning-Diagnostics-Provider/Admin' $evtx 2>&1
if (Test-Path $evtx) { Log " exported $evtx" }
} catch {
Log " WARN: wevtutil export threw: $_"
}
# --- Set OOBE complete (only reached if PPKG didn't trigger immediate reboot) ---
Log "Setting OOBE as complete..."
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\OOBE" /v OOBEComplete /t REG_DWORD /d 1 /f | Out-Null

View File

@@ -137,8 +137,9 @@ if "%standard_choice%"=="1" set PCSUBTYPE=Timeclock
if "%standard_choice%"=="2" set PCSUBTYPE=Machine
if "%PCSUBTYPE%"=="" goto standard_menu
REM --- Machine number (Standard only) ---
REM --- Machine number (Standard-Machine only; Timeclock PCs do not use one) ---
set MACHINENUM=9999
if "%PCSUBTYPE%"=="Timeclock" goto skip_standard_menu
echo.
set /p MACHINENUM=Enter machine number (digits, or Enter for 9999):
if "%MACHINENUM%"=="" set MACHINENUM=9999

View File

@@ -137,8 +137,9 @@ if "%standard_choice%"=="1" set PCSUBTYPE=Timeclock
if "%standard_choice%"=="2" set PCSUBTYPE=Machine
if "%PCSUBTYPE%"=="" goto standard_menu
REM --- Machine number (Standard only) ---
REM --- Machine number (Standard-Machine only; Timeclock PCs do not use one) ---
set MACHINENUM=9999
if "%PCSUBTYPE%"=="Timeclock" goto skip_standard_menu
echo.
set /p MACHINENUM=Enter machine number (digits, or Enter for 9999):
if "%MACHINENUM%"=="" set MACHINENUM=9999