diff --git a/scripts/Bootstrap/Install-AutopilotMonitor.ps1 b/scripts/Bootstrap/Install-AutopilotMonitor.ps1 index da8de18c..abb768c7 100644 --- a/scripts/Bootstrap/Install-AutopilotMonitor.ps1 +++ b/scripts/Bootstrap/Install-AutopilotMonitor.ps1 @@ -40,7 +40,7 @@ .CHANGELOG 2026-03-31 Replaced OS age + MDM pre-flight checks with multi-signal guard: registry deployment marker, WMI/filesystem user profile detection, - lastloggedonUser set, explorer.exe running, and 12h bootstrap window. + lastloggedonUser set, and 12h bootstrap window. 2026-03-30 Fixed non-ASCII characters (em-dashes, Unicode symbols) that broke script parsing under PowerShell 5.1 / IME AgentExecutor 2026-03-29 Hardened integrity check: SHA-256 verification via version.json @@ -111,10 +111,10 @@ try { # Guard 1: Ghost re-installs (registry marker from previous deployment) # Guard 2: Productive devices (real user profile exists -- WMI + filesystem) # Guard 3: Productive devices (a real user has logged on before) - # Guard 4: Productive devices (explorer.exe running = user desktop active) - # Guard 5: Bootstrap window expired (device uptime > 12h without agent) - # Guard 6: Agent binary already present from a previous run + # Guard 4: Bootstrap window expired (device uptime > 12h without agent) + # Guard 5: Agent binary already present from a previous run # NOTE: OOBEInProgress is NOT used -- it is unreliable (observed =0 during active enrollment). + # NOTE: explorer.exe is NOT used -- it runs even in early OOBE right after script execution. # Guard 1: Agent was already deployed on this device (registry marker survives self-destruct) $deployed = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\AutopilotMonitor' -Name 'Deployed' -ErrorAction SilentlyContinue).Deployed @@ -153,13 +153,7 @@ try { exit 0 } - # Guard 4: explorer.exe running -- during Device ESP no desktop shell is active - if (Get-Process explorer -ErrorAction SilentlyContinue) { - Write-Log "SKIP: explorer.exe is running. Device appears beyond initial enrollment." - exit 0 - } - - # Guard 5: Bootstrap window check (no key, no user profiles, but device running too long) + # Guard 4: Bootstrap window check (no key, no user profiles, but device running too long) # NOT "how long may enrollment take" -- agent handles that internally (6h emergency break). # This is "how old can the OOBE state be before I no longer trust it for initial install". # 12h bootstrap window vs 6h agent emergency break = consistent layered approach. @@ -172,7 +166,7 @@ try { exit 0 } - # Guard 6: Is the agent already installed? (leftover from previous run) + # Guard 5: Is the agent already installed? (leftover from previous run) if (Test-Path $AgentBinPath) { $existingAgent = Get-ChildItem -Path $AgentBinPath -Filter "AutopilotMonitor.Agent.exe" -ErrorAction SilentlyContinue if ($existingAgent) { @@ -181,7 +175,7 @@ try { } } - Write-Log "Pre-flight checks passed -- no prior deployment, no real user profiles, no logged-on user, no explorer" + Write-Log "Pre-flight checks passed -- no prior deployment, no real user profiles, no logged-on user, within bootstrap window" # Download and extract agent binaries $agentExePath = Join-Path $AgentBinPath "AutopilotMonitor.Agent.exe" diff --git a/scripts/Bootstrap/Test-ShouldBootstrapAgent.ps1 b/scripts/Bootstrap/Test-ShouldBootstrapAgent.ps1 index 39cedcc4..d22a0b3c 100644 --- a/scripts/Bootstrap/Test-ShouldBootstrapAgent.ps1 +++ b/scripts/Bootstrap/Test-ShouldBootstrapAgent.ps1 @@ -110,17 +110,7 @@ if ($lastLoggedOnUser -and $lastLoggedOnUser -notmatch 'defaultuser\d*') { Write-Step -Status 'PASS' -Message "Guard 3: No real LastLoggedOnUser (value: '$lastLoggedOnUser')." } -# Guard 4: explorer.exe running -- during Device ESP no desktop shell is active -$explorerRunning = $null -ne (Get-Process explorer -ErrorAction SilentlyContinue) -if ($explorerRunning) { - Write-Step -Status 'SKIP' -Message 'Guard 4: explorer.exe is running. Device appears beyond initial enrollment.' - $wouldInstall = $false - $reasons.Add('explorer.exe is running') -} else { - Write-Step -Status 'PASS' -Message 'Guard 4: explorer.exe is not running.' -} - -# Guard 5: Bootstrap window check +# Guard 4: Bootstrap window check # NOT "how long may enrollment take" -- agent handles that internally (6h emergency break). # This is "how old can the OOBE state be before I no longer trust it for initial install". # 12h bootstrap window vs 6h agent emergency break = consistent layered approach. @@ -133,24 +123,24 @@ try { $uptimeHours = ((Get-Date) - $lastBoot).TotalHours if ($uptimeHours -gt $MaxBootstrapWindowHours) { - Write-Step -Status 'SKIP' -Message "Guard 5: Device uptime is $([int]$uptimeHours)h. Older than accepted bootstrap window of ${MaxBootstrapWindowHours}h." + Write-Step -Status 'SKIP' -Message "Guard 4: Device uptime is $([int]$uptimeHours)h. Older than accepted bootstrap window of ${MaxBootstrapWindowHours}h." $wouldInstall = $false $reasons.Add("Uptime exceeds bootstrap window: $([int]$uptimeHours)h > ${MaxBootstrapWindowHours}h") } else { - Write-Step -Status 'PASS' -Message "Guard 5: Device uptime is $([int]$uptimeHours)h and within bootstrap window of ${MaxBootstrapWindowHours}h." + Write-Step -Status 'PASS' -Message "Guard 4: Device uptime is $([int]$uptimeHours)h and within bootstrap window of ${MaxBootstrapWindowHours}h." } } catch { - Write-Step -Status 'WARN' -Message 'Guard 5: Could not determine LastBootUpTime / uptime.' + Write-Step -Status 'WARN' -Message 'Guard 4: Could not determine LastBootUpTime / uptime.' } -# Guard 6: Agent binary already present +# Guard 4: Agent binary already present if (Test-Path $AgentExePath) { - Write-Step -Status 'SKIP' -Message "Guard 6: Agent already installed at '$AgentExePath'." + Write-Step -Status 'SKIP' -Message "Guard 5: Agent already installed at '$AgentExePath'." $wouldInstall = $false $reasons.Add("Agent binary already present: $AgentExePath") } else { - Write-Step -Status 'PASS' -Message "Guard 6: Agent binary not present at '$AgentExePath'." + Write-Step -Status 'PASS' -Message "Guard 5: Agent binary not present at '$AgentExePath'." } Write-Host '' @@ -179,7 +169,6 @@ Write-Host '=== Raw Values ===' Write-Host "Deployed marker : $deployed" Write-Host "DetectedProfileNames : $($profileNames -join ', ')" Write-Host "LastLoggedOnUser : $lastLoggedOnUser" -Write-Host "ExplorerRunning : $explorerRunning" Write-Host "MaxBootstrapWindowHours : $MaxBootstrapWindowHours" Write-Host "LastBootUpTime : $lastBoot" Write-Host "UptimeHours : $([string]$uptimeHours)" diff --git a/src/Web/autopilot-monitor-web/app/docs/sections/SectionAgentSetup.tsx b/src/Web/autopilot-monitor-web/app/docs/sections/SectionAgentSetup.tsx index 234a53b2..4b4bbc23 100644 --- a/src/Web/autopilot-monitor-web/app/docs/sections/SectionAgentSetup.tsx +++ b/src/Web/autopilot-monitor-web/app/docs/sections/SectionAgentSetup.tsx @@ -44,12 +44,6 @@ export function SectionAgentSetup() { LastLoggedOnUser{" "} in the LogonUI registry — during Device ESP no real user has logged on yet. A real username indicates the device has been used interactively. -