bugfix bootstrap

This commit is contained in:
Oliver Kieselbach
2026-03-31 23:54:46 +02:00
parent 02325a302d
commit 7596b586b0
3 changed files with 14 additions and 37 deletions
+7 -13
View File
@@ -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"
@@ -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)"
@@ -44,12 +44,6 @@ export function SectionAgentSetup() {
<span className="font-mono text-xs bg-green-100 px-1.5 py-0.5 rounded">LastLoggedOnUser</span>{" "}
in the LogonUI registry — during Device ESP no real user has logged on yet. A real username indicates the device has been used interactively.</span>
</li>
<li className="flex items-start gap-2">
<span className="text-green-600 font-bold mt-0.5 shrink-0">✓</span>
<span><strong>No desktop shell:</strong> Checks if{" "}
<span className="font-mono text-xs bg-green-100 px-1.5 py-0.5 rounded">explorer.exe</span>{" "}
is running — during Device ESP the enrollment status page is shown instead of the Windows desktop. A running explorer process indicates the device is beyond initial enrollment.</span>
</li>
<li className="flex items-start gap-2">
<span className="text-green-600 font-bold mt-0.5 shrink-0">✓</span>
<span><strong>Within bootstrap window:</strong> Device uptime must be under 12 hours. Prevents installation on devices that have been sitting powered on without completing enrollment. Sleep and standby do not reset this timer.</span>