-
Notifications
You must be signed in to change notification settings - Fork 1
Autopilot and the ESP
BootstrapMate is usually deployed to run during Windows Autopilot provisioning. This page describes what that window actually looks like on the device, and — more importantly — what BootstrapMate does and does not know about it.
The Out-of-Box Experience (OOBE) is the first-boot sequence a Windows device runs before anyone has a desktop: region and keyboard, network, and then, on an Autopilot-registered device, Entra ID join and MDM enrolment.
The Enrollment Status Page (ESP) is the blocking screen Intune shows during and just after
that. It has two phases. The device phase runs before any user signs in; everything
installed here runs in the SYSTEM context and there is no user profile, no interactive
desktop, and no HKCU for a real user. The user phase runs after the first sign-in, once
a user token and profile exist. Intune decides when each phase is complete based on the apps
you have marked as blocking.
For BootstrapMate's purposes, what matters is that the device phase has no user session and the user phase does.
Stated plainly, because it is easy to assume otherwise: there is no OOBE detection, no ESP detection and no enrolment detection anywhere in the codebase. Nothing probes for an ESP registry key, nothing looks for the ESP shell process, nothing tests for session 0, and nothing waits for a user to log in.
The two manifest phases, setupassistant and userland, are labels within a single
process run. ProcessManifest runs every setupassistant item and then immediately runs
every userland item, in the same await chain, in the same process, under the same token.
There is no pause between them and no second invocation.
ManagementDetector, despite its name, detects managed settings — values under
HKLM\SOFTWARE\Policies\BootstrapMate. It does not detect MDM enrolment or provisioning
state.
So the device-phase versus user-phase distinction comes entirely from when you invoke the CLI, not from any branch inside it.
The MSI's install-time run is fired through the BootstrapMate Self-Heal scheduled task,
which is registered /RU SYSTEM. The daily 03:00 run uses the same task. In both cases
both phases execute as SYSTEM. If you deploy the MSI as a device-context Win32 app during
the ESP device phase, your userland items run as SYSTEM before any user has signed in.
Guidance that follows from that:
- Treat
userlandas "second", not as "in a user session". Anything that genuinely needs an interactive user token, a user profile, orHKCUwill not get one from a SYSTEM-context run. Deliver that work through a different mechanism — a logon task, a user-context Intune app, or a per-user configuration policy — and useuserlandfor ordering only. - If you want a run that really is in the user's context, invoke
managedbootstrapinstall.exeyourself at that point, elevated, with a manifest whosesetupassistantarray is absent so that phase is markedSkipped. - Keep ESP-blocking work bounded. The MSI's custom action starts the scheduled task and ignores its result, so the MSI can finish while packages are still installing. If you mark the app as blocking, ESP will pass as soon as the MSI completes and its detection rule matches — not when the manifest has finished. See Deployment for what the shipped detection scripts actually detect.
- Do not rely on a reboot. There is no pending-reboot detection, no resume-after-reboot state
machine, and no reboot handling of any kind.
/norestartis passed to every MSI install, and theRebootsetting is never read. The only thing that resumes work is the daily task re-running the entire manifest. - Expect signature checks to work offline-ish. Authenticode verification runs with revocation checking deliberately disabled, because OCSP and CRL fetches are unreliable on the partly configured network of an OOBE session. See Security and Package Verification.
- Never put an interactive flag in an ESP invocation.
--reset-chocolateyand the unelevated-startup path both callConsole.ReadLine()and will block forever under a scheduled task.
On macOS the same window is Setup Assistant plus the MDM bootstrap, and the sibling tool
uses the same setupassistant and userland vocabulary — that vocabulary is inherited from
InstallApplications on the Mac side. The macOS implementation handles the phase split
differently, so read that page before assuming behaviour carries across:
https://github.com/bootstrapmate/bootstrapmate-macintosh/wiki/Setup-Assistant-and-MDM-Bootstrap