From 86ae616b3bc1330b6617cb53203dcc337d48e6a1 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Thu, 30 Apr 2026 18:05:51 +0200 Subject: [PATCH] feat(bootstrap): verify runtime process started after schtasks /Run schtasks reports SUCCESS as soon as the run is queued, not once the process is actually alive. A silent block (AV/EDR, AppLocker/WDAC) or Task Scheduler defer during OOBE would otherwise stay invisible until the next reboot triggers the task via /SC ONSTART. After --install, poll Get-Process for AutopilotMonitor.Agent.V2 every 500ms up to 10s. Log pid + StartTime on success, or a clear WARNING that points operators at TaskScheduler/Operational + AV/EDR logs on failure. Same change applied to the production and dev variants. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Install-AutopilotMonitor-v2-dev.ps1 | 23 +++++++++++++++++++ .../Bootstrap/Install-AutopilotMonitor-v2.ps1 | 23 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/scripts/Bootstrap/Install-AutopilotMonitor-v2-dev.ps1 b/scripts/Bootstrap/Install-AutopilotMonitor-v2-dev.ps1 index 062cdd7d..513225f7 100644 --- a/scripts/Bootstrap/Install-AutopilotMonitor-v2-dev.ps1 +++ b/scripts/Bootstrap/Install-AutopilotMonitor-v2-dev.ps1 @@ -260,6 +260,29 @@ try { throw "Agent install failed with exit code $installExitCode" } Write-Log "Agent install mode completed successfully" + + # Verify the runtime process actually started after schtasks /Run. + # schtasks reports SUCCESS as soon as the run is queued, not once the process + # is alive. Silent launch failures (AV/EDR block, AppLocker/WDAC, scheduler + # defer during OOBE) would otherwise stay invisible until the next reboot + # triggers the task via /SC ONSTART. + $runtimeProcessName = 'AutopilotMonitor.Agent.V2' + $verifyTimeoutSec = 10 + $verifyDeadline = (Get-Date).AddSeconds($verifyTimeoutSec) + $runtimeProc = $null + while ((Get-Date) -lt $verifyDeadline) { + $runtimeProc = Get-Process -Name $runtimeProcessName -ErrorAction SilentlyContinue | Select-Object -First 1 + if ($null -ne $runtimeProc) { break } + Start-Sleep -Milliseconds 500 + } + if ($null -ne $runtimeProc) { + $startedUtc = 'unavailable' + try { $startedUtc = $runtimeProc.StartTime.ToUniversalTime().ToString('o') } catch { } + Write-Log ("Runtime process verified: name={0}.exe pid={1} startedUtc={2}" -f $runtimeProcessName, $runtimeProc.Id, $startedUtc) + } else { + Write-Log ("WARNING: Runtime process verification FAILED. schtasks /Run was reported SUCCESS by --install, but no '{0}.exe' process appeared within {1}s. Likely silent block (AV/EDR, AppLocker/WDAC) or Task Scheduler defer. Agent may not start until next system boot ('/SC ONSTART'). Check Event Viewer > Microsoft > Windows > TaskScheduler/Operational and AV/EDR logs for '{0}.exe'." -f $runtimeProcessName, $verifyTimeoutSec) + } + Write-Log "===== Bootstrap Completed Successfully (DEV) =====" exit 0 diff --git a/scripts/Bootstrap/Install-AutopilotMonitor-v2.ps1 b/scripts/Bootstrap/Install-AutopilotMonitor-v2.ps1 index 4edec32d..c070ba14 100644 --- a/scripts/Bootstrap/Install-AutopilotMonitor-v2.ps1 +++ b/scripts/Bootstrap/Install-AutopilotMonitor-v2.ps1 @@ -303,6 +303,29 @@ try { throw "Agent install failed with exit code $installExitCode" } Write-Log "Agent install mode completed successfully" + + # Verify the runtime process actually started after schtasks /Run. + # schtasks reports SUCCESS as soon as the run is queued, not once the process + # is alive. Silent launch failures (AV/EDR block, AppLocker/WDAC, scheduler + # defer during OOBE) would otherwise stay invisible until the next reboot + # triggers the task via /SC ONSTART. + $runtimeProcessName = 'AutopilotMonitor.Agent.V2' + $verifyTimeoutSec = 10 + $verifyDeadline = (Get-Date).AddSeconds($verifyTimeoutSec) + $runtimeProc = $null + while ((Get-Date) -lt $verifyDeadline) { + $runtimeProc = Get-Process -Name $runtimeProcessName -ErrorAction SilentlyContinue | Select-Object -First 1 + if ($null -ne $runtimeProc) { break } + Start-Sleep -Milliseconds 500 + } + if ($null -ne $runtimeProc) { + $startedUtc = 'unavailable' + try { $startedUtc = $runtimeProc.StartTime.ToUniversalTime().ToString('o') } catch { } + Write-Log ("Runtime process verified: name={0}.exe pid={1} startedUtc={2}" -f $runtimeProcessName, $runtimeProc.Id, $startedUtc) + } else { + Write-Log ("WARNING: Runtime process verification FAILED. schtasks /Run was reported SUCCESS by --install, but no '{0}.exe' process appeared within {1}s. Likely silent block (AV/EDR, AppLocker/WDAC) or Task Scheduler defer. Agent may not start until next system boot ('/SC ONSTART'). Check Event Viewer > Microsoft > Windows > TaskScheduler/Operational and AV/EDR logs for '{0}.exe'." -f $runtimeProcessName, $verifyTimeoutSec) + } + Write-Log "===== Bootstrap Completed Successfully =====" exit 0