Autopilot: deploy an app only during provisioning with an ESP requirement script

The usual answer to "deploy an app only during Autopilot provisioning" is a group: put new devices in it, assign the app as required, and pull them out later. A required assignment can't tell a laptop in OOBE from one that's been in production for two years, and the group cleanup is the step that gets skipped.
What follows is how we handle it in tenants we assess: keep the required assignment, add a requirement script, and be honest about what that script can and can't detect.
Why a required assignment hits production devices too
ESP only tracks what is already assigned. Microsoft Learn says plainly that the blocking apps list in the ESP profile filters which assigned apps ESP waits for. It doesn't choose what gets installed. Assign a debloat script or a one-time driver tool as required to All Devices so ESP will wait for it, and every enrolled device runs it at its next check-in. That's the scenario in the Oct 12 r/Intune thread: a cleanup app that strips non-approved apps is safe on a new device and harmful when it runs again on a machine someone has been using for a year.
What breaks it:
- Stop treating the ESP blocking list as targeting. It's a wait list. The assignment still decides scope.
- List which of your required apps are setup-only. Most aren't. As one commenter in the thread put it, if an app is safe on every device and its detection rule already shows it installed, it doesn't need special handling.
- Leave group-tag shuffles out of it. A tag that gets removed after provisioning works until someone forgets to remove it.
The ESP requirement script: Applicable during setup, Not applicable after
Win32 apps support script requirement rules. Patch My PC's knowledge base article on preventing a required app from reinstalling describes the shape: the script prints Applicable when the app should install, and the requirement is set to String, Equals, Applicable. When the script prints nothing, Intune marks the app Not applicable for that device and the required assignment does nothing there. Point the same pattern at "is this device still in setup?" and you have a provisioning-only app.
What breaks it:
- Run it as System, 64-bit. Learn's ESP known issues note that scripts running with the logged-on credentials might not execute during ESP.
- Add the app to the ESP blocking list if setup should wait for it. Otherwise, in user-driven and self-deploying flows, Learn says a non-blocking Win32 app doesn't install until after ESP completes, and by then your script returns Not applicable.
- Plan for a failed install. If the app fails during ESP, the same rule keeps it from retrying later. Decide up front whether that's acceptable or whether a remediation picks it up.
The detection itself: three community checks, none documented by Microsoft
This is the part to be careful about. Learn's Enrollment Status Page documentation doesn't describe a supported "running in ESP" signal. The checks admins use are observations of how setup looks today:
- defaultuser0. The script checks whether
explorer.exeis owned bydefaultuser0, the temporary setup account. One commenter noted it can persist or leave traces after setup. - SecurityHealthSystray absent. If the Windows Security tray process isn't running, the script assumes the device is still in setup.
- An OOBE API check. Michael Niehaus's "Detecting when you are in OOBE" post (oofhours.com) calls a Windows API instead of watching processes. Commenters preferred it over the process checks.
What breaks it:
- Pick one and test it in every flow you run. User-driven, pre-provisioning technician flow, and self-deploying look different on the device, and a check that passes in one can fail in another.
- Re-test after feature updates. A process name or setup account isn't a contract, so a Windows release can change the result without notice.
- Log the result. Have the script write what it saw to a file under
C:\ProgramDataso a wrong answer is visible later.
What "good" looks like: the five-move baseline
- Name the setup-only apps. Keep that list short and give a reason for each one.
- Add one requirement script in System context, String equals
Applicable, on each of those Win32 apps. Keep the required assignment. - Put them on the ESP blocking list so setup waits for them instead of skipping past.
- Test each Autopilot flow you use on a real device and read the script's own log.
- Check one production device. The app should show Not applicable in Intune, and AppWorkload.log should record the requirement as not met.
None of this needs new licensing. All of it is visible in the Intune admin center and the IME logs.
If you need provisioning-only apps without breaking devices already in production, our Windows Autopilot Consulting Assess path maps which apps belong in ESP and which belong after it.
Book a 30-minute Autopilot diagnostic. We check the requirement rule, the ESP blocking list, and one production device's logs before you widen the assignment.
Book Autopilot diagnostic →The uncomfortable question
If a required "setup-only" app ran on your production fleet tonight, would you know? Most tenants only find out when a user's approved app disappears. Open the app's device install status in Intune and sort by install date. If devices enrolled months ago show a recent install, your requirement rule isn't doing what you think.
Frequently asked questions
How do I deploy an Intune app only during Autopilot provisioning?
Keep the app as a required Win32 assignment so ESP can track it, then add a script requirement rule that returns Applicable only while the device is still in setup. Devices already in production evaluate the same rule, get Not applicable, and skip the install.
Does Microsoft support a way to detect that a device is in ESP?
Microsoft Learn's Enrollment Status Page documentation doesn't describe a supported "running in ESP" signal. Checks such as the defaultuser0 account, the SecurityHealthSystray process, or an OOBE API call are community methods. Test whichever you choose in every Autopilot flow you run.
How can I tell the requirement script blocked an install on a production device?
The app shows Not applicable for that device in Intune, and Company Portal reports requirements not met. Patch My PC's write-up of the same pattern shows AppWorkload.log recording ScriptRequirementRuleNotMet.
Book a 30-minute Autopilot diagnostic. We check the requirement rule, the ESP blocking list, and one production device's logs before you widen the assignment.
Book Autopilot diagnostic →Get the next Insights post by email.
Keep reading
Autopilot hash import stuck at Syncing: why the device never gets its profile
Autopilot hash import stuck at Syncing? Check service health, the registration error, then group tag and profile assignment before re-uploading.
Read the article →Autopilot ESP timeout 0x800705b4: TPM attestation and Device Preparation before you wipe again
Autopilot ESP 0x800705b4 is a timeout, not a root cause. Separate TPM attestation, required-app waits, and hybrid hangs before another wipe.
Read the article →Autopilot pre-provision fails with Windows App 0x80244018: Store CDN vs required apps in the technician flow
Autopilot pre-provision Windows App 0x80244018: separate Store CDN / HTTP 403 intermittency from required-app design in the technician flow.
Read the article →

