Have you ever had apps that just refuse to uninstall because the Intune Management Extension (Microsoft IME) insists the device is stuck in the Enrollment Status Page (ESP) Account Setup phase?
This blog explores that exact frustration, breaking down how the Microsoft IME tracks the Enrollment Status Page (ESP) phases and what happens when it thinks a device hasn’t left Account Setup. We’ll also uncover the inner mechanics of ESP checks and reveal the secrets behind EnrollmentStatusTracking CSP and WMI calls.
Introduction: A Reddit Puzzle That Led to a Deep Dive into ESP Mysteries
It all started with a Reddit post: a user was struggling with Hybrid Join devices perpetually stuck in the ESP Account Setup phase. What initially seemed like a simple issue with app uninstalls quickly revealed something deeper.
This post piqued my curiosity—not just because of the stuck apps (Apps not being uninstalled), but because multiple attempts to fix the problem hadn’t moved the devices past AccountSetup. I realized this case might expose fundamental insights into how the Enrollment Status Page (Microsoft ESP) integrates with the Intune Management Extension (Microsoft IME) to handle device provisioning and tracking.
This raised essential questions about how ESP determines app installation status, the roles of WMI and CSPs in setup, and how uninstall issues (like those this Reddit user faced) impact flow. This led me to dissect ESP’s intricate checks and IME interactions, which I’ll break down here to give you the full picture.
Now, let’s examine these checks and dive deep into ESP’s flow to understand how to spot where things might go wrong.
ESP and IME: Gatekeepers of Apps
The Enrollment Status Page (ESP) is the mechanism that ensures a device completes critical setup steps (like app installs/powershell scripts and policies) before users gain full access to the desktop environment. The IME, meanwhile, is responsible for managing Win32 app installations and PowerShell scripts, on Intune-managed devices.
The Intune Management Extension (IME) relies on the GetEspPhase function and the CheckDeviceAndAccountSetupStateWithWmi to identify the current ESP phase.
To determine if a device is ready, the CheckDeviceAndAccountSetupStateWithWmi IME function examines specific registry entries and settings, including the sidecar CSP provider, which reflects the device’s readiness and phase state.
If ESP and IME fall out of sync, like in the Reddit case, the device can become “stuck” in AccountSetup, even post-enrollment. After noticing the IME was stuck in the Account Setup, my first idea was to use the Get-AutopilotDiagnostics tool.
Get-AutopilotDiagnostics
When the ESP phase decided to get stuck, I pulled out Get-AutopilotDiagnostics, a PowerShell script that’s solid for capturing what’s happening under the hood during Autopilot provisioning. This tool gives you the full scoop on ESP stages, device details, policy progress, and even app install statuses. If an app or policy stalls out, Get-AutopilotDiagnostics will usually flag it for you.
But here’s the twist: while the script should normally help when your Autopilot enrollment fails, it didn’t reveal the full story this time around. When running the get-autopilotdiagnostics script, it showed me that the device ESP was still enabled, while the IME Appworkload.log told me the device was in the accountsetup?
If you want to know how to use the get-autopilotdiagnostics tool to troubleshoot your Autopilot enrollment, please read this blog: Get-AutopilotDiagnostics | Troubleshooting Autopilot Issues
Besides the mention of the Device ESP being enabled, it didn’t show me anything more useful. The specific interactions between Intune Management Extension and the ESP phases ran a bit deeper than what Get-AutopilotDiagnostics could dig up. Still, it’s a great first step if you’re troubleshooting Autopilot or ESP issues and need a snapshot of what’s working (or not) in real-time.
Digging Deeper into IME Behavior
As I dug deeper, it became clear that IME wasn’t just stuck; it thought the device was trapped in the ESP AccountSetup phase, effectively blocking critical uninstalls. This is where things got interesting: tracking how IME’s ESP checks interacted with app installations and policies showed that something was definitely off.
When we started investigating, it became clear that the Microsoft IME thought the device was stuck in the ESP AccountSetup phase, blocking required uninstalls.
If you know the GetEspPhase flow, it will make some sense; let me explain. After asking the OP a few questions, we determined that the FirstSync key (holding the user’s SID) was missing.
If the firstsync key is missing, the IME couldn’t confirm the initial user provisioning. (IsSyncDone)
Besides the firstsync key totally missing, the persistent sidecar key also kept IME in “in ESP.”
The solution? I asked the OP to Delete the sidecar key. After deleting the key, a reboot, and letting the IME recheck, it showed “NotInEsp” in the logs
With the IME no longer thinking it was in the AccountPhase, the uninstalls started working.
Cool, problem solved, right? Well, as mentioned in the introduction, this issue got me curious about how the IME tries to detect the correct Microsoft ESP Phase. (NotInesp/DevicePreparation/DeviceSetup/AccountSetup)
Shall we focus on that important part now that the issue has been fixed?
Get ESP Phase IME Flow
Understanding the whole ESP flow is critical for troubleshooting why devices appear stuck. Here’s the process ESP follows to verify whether a device is ready for full access. Below, you will find the corresponding description of each step in the process.
1. Start – CheckEspPhase
- Description: Begins the Enrollment Status Page (ESP) phase check to determine if the device should proceed through the ESP process.
- Code Reference:
EspHelper.CheckEspPhase
2. Is OS Version 19H1 or Later?
- Description: Checks if the OS version is 19H1 or newer, as ESP is only supported on OS versions 19H1 and above.
- Code Reference:
EnvironmentHelper.Is19H1OrLaterBuild()
- Outcome: If No, proceed to Step 3.
3. Return NotInEsp if OS < 19H1
- Description: Ends the ESP flow if the OS version is too old to support ESP.
- Outcome: ESP process ends with the device marked as
NotInEsp
.
4. Found FirstSync Key?
- Description: Checks for the existence of the FirstSync registry key to verify if initial provisioning has started.
- Registry Path:
HKLM\SOFTWARE\Microsoft\Enrollments\<GUID>\FirstSync
- Outcome: If No, proceed to Step 5.
5. Check Device Provisioning in First Sync
- Description: Validates device provisioning status directly from registry entries if the FirstSync key is not found.
- Registry Path:
HKLM\SOFTWARE\Microsoft\Enrollments\
- Outcome: If provisioning is found, proceed to Step 6; otherwise, proceed to Step 21.
6. Skip Device and User Status Pages?
- Description: Checks if both
SkipDeviceStatusPage
andSkipUserStatusPage
are set, meaning the ESP should be skipped. - Registry Path:
HKLM\SOFTWARE\Microsoft\Enrollments\<GUID>\FirstSync\SkipDeviceStatusPage
andSkipUserStatusPage
- Outcome: If Yes, ESP ends at Step 7; if No, continue to Step 8.
7. Return NotInEsp if Skipping Both Pages
- Description: Ends ESP if both device and user pages are skipped.
- Outcome: ESP process ends with the device marked as
NotInEsp
.
8. IsSyncDone if SkipUserStatusPage == No
- Description: Determines if synchronization is complete based on whether the User Status page was skipped.
- Outcome: If Yes, flow exits with NotInEsp status; if No, proceed to Step 9.
9. Check SidecarCSP Provider State
- Description: Checks the status of the SidecarCSP provider to track device readiness for provisioning.
- CSP Path:
./Vendor/MSFT/EnrollmentStatusTracking/DevicePreparation/PolicyProviders/Sidecar
- Code Reference:
EspHelper.GetSidecarProviderState
10. Sidecar Provider State – NotInstalled / NotRequired / Completed
- Description: Validates the installation state of SidecarCSP.
- Outcome:
- NotInstalled: Proceed to Step 11.
- NotRequired: Ends with Step 14.
- Completed: Proceed to Step 15.
11. Set SidecarProvider State to Completed
- Description: Updates the state of SidecarCSP to
Completed
to signal that Sidecar requirements are met. - CSP Path:
./Vendor/MSFT/EnrollmentStatusTracking/DevicePreparation/PolicyProviders/Sidecar
- Code Reference:
EspHelper.SetSidecarProviderState
12. Track Resource Types – Apps
- Description: Configures tracked resource types under Sidecar to include apps for tracking purposes.
- CSP Path:
./Vendor/MSFT/EnrollmentStatusTracking/DevicePreparation/PolicyProviders/Sidecar/TrackedResourceTypes
- Code Reference:
EspHelper.SetSidecarProviderTrackedResourceTypes
13. Enter DeviceSetup Phase
- Description: Sets the device to the
DeviceSetup
phase to continue provisioning at the device level. - Outcome: Continue to Step 15.
14. Return NotInEsp if Sidecar Not Required
- Description: Ends ESP if Sidecar is marked as
NotRequired
. - Outcome: ESP process ends with the device marked as
NotInEsp
.
15. Check Device Setup State with WMI
- Description: Checks the provisioning state of the device through WMI for device and account setups.
- CSP Path:
MDM_EnrollmentStatusTracking_Setup01
- Code Reference:
EspHelper.CheckDeviceAndAccountSetupStateWithWmi
16. Device Provisioning Completed & Policies Created?
- Description: Checks both
HasProvisioningCompleted
andTrackingPoliciesCreated
flags in Sidecar. - CSP Path:
./Vendor/MSFT/EnrollmentStatusTracking/DevicePreparation/PolicyProviders/Sidecar
- Code Reference:
EspHelper.GetHasProvisioningCompleted
andGetSidecarTrackingPoliciesCreated
- Outcome: If complete, proceed to Step 21; otherwise, continue to Step 17.
17. Check Device-Level Tracking Apps
- Description: Retrieves the installation state of tracked apps at the device level.
- CSP Path:
MDM_EnrollmentStatusTracking_Tracking03_02
- Code Reference:
EspHelper.GetTrackingApps
18. Are All Device Apps Installed?
- Description: Verifies if all tracked apps marked for device installation are fully installed.
- Registry Path:
HKLM\SOFTWARE\Microsoft\Enrollments\<GUID>\FirstSync
- Outcome: If Yes, continue to Step 20; if No, go to Step 19.
19. DeviceSetup Phase if Apps Pending
- Description: Device remains in the DeviceSetup phase if apps are still in progress or NotInstalled.
- Outcome: Loops back to Step 13 to re-check status.
20. Provisioning Completion Check
- Description: Ensures all apps are installed and checks if provisioning has fully completed.
- Code Reference:
EspHelper.GetHasProvisioningCompleted
- Outcome: If complete, proceed to Step 21.
21. Proceed to AccountSetup Phase
- Description: Moves to
AccountSetup
to initiate user-level provisioning. - Outcome: Continue to Step 22.
22. Account Provisioning Check
- Description: Checks account provisioning and
TrackingPoliciesCreated
flag at the account level. - CSP Path:
MDM_EnrollmentStatusTracking_Tracking03_02
- Code Reference:
EspHelper.GetSidecarTrackingPoliciesCreated
23. Check Account-Level Tracking Apps
- Description: Retrieves the installation state of tracked apps for the account.
- CSP Path:
MDM_EnrollmentStatusTracking_Tracking03_02
- Code Reference:
EspHelper.GetTrackingApps
24. Are All Account Apps Installed?
- Description: Verifies if all account-specific tracked apps are fully installed.
- Outcome: If Yes, proceed to Step 25.
25. Return NotInEsp if All Apps Done
- Description: Ends ESP once all apps for both device and account have completed installation.
- Outcome: ESP process ends with the device marked as
NotInEsp
.
Summary of Critical Keys and Expected Values for ESP Completion
To ensure that a device exits the Enrollment Status Page (ESP) as completed, the following registry keys and values should exist and be correctly set. This table also includes details on how ESP behaves if certain keys, like the Sidecar CSP, are missing.
Registry Path | Value | Expected Data | What if Missing? |
---|---|---|---|
Device-Level Provisioning StatusHKLM\SOFTWARE\Microsoft\Enrollments\<GUID>\FirstSync | ProvisioningStatus | 1 (Success) | If missing, the device will not complete the DeviceSetup Phase in ESP and remain in the provisioning process. |
IsSyncDone | 1 (Sync complete) | If missing, ESP considers the provisioning incomplete and may retry or stall. | |
IsServerProvisioningDone | 1 (Server provisioning complete) | If missing, ESP may interpret that server-side provisioning is still ongoing and may stay in the ESP flow. | |
HasProvisioningCompleted | 1 (Provisioning completed) | If missing, ESP won’t exit as it assumes provisioning is not complete. | |
User-Specific Provisioning StatusHKLM\SOFTWARE\Microsoft\Enrollments\<GUID>\FirstSync\<UserSID> | IsSyncDone | 1 (Sync complete for user) | Without this, ESP may keep the device in the AccountSetup Phase waiting for user-specific provisioning to complete. |
HasProvisioningCompleted | 1 (Provisioning completed for user) | Missing this key causes ESP to remain in AccountSetup Phase or delay its exit. | |
Skip Status Page Flags (Optional, influences ESP bypass)HKLM\SOFTWARE\Microsoft\Enrollments\<GUID>\FirstSync | SkipDeviceStatusPage | 1 (Skip) | If both this and SkipUserStatusPage are 1 , ESP will be bypassed and the device exits as NotInEsp. |
SkipUserStatusPage | 1 (Skip) | Alone, this flag skips only the user status page but retains device checks. | |
Sidecar Component (if applicable)HKLM\SOFTWARE\Microsoft\Windows\Autopilot\EnrollmentStatusTracking\Device\DevicePreparation\PolicyProviders\SideCar | InstallationState | 3 (Completed) | If InstallationState key is missing or if SideCar CSP is absent:ESP will interpret Sidecar as NotRequired and skip Sidecar-specific checks, potentially marking the device as NotInEsp if all other provisioning phases are complete. |
Besides this overview I also need to add something intriguing because if somehow the HKLM\SOFTWARE\Microsoft\Enrollments\<GUID>\FirstSync\<UserSID>
is missing, you could configure the isserverprovisioningdone back to zero and sync the device
After syncing the device the OMADMClient would recreate that usersid folder and would mark the user provisioning as done
The Takeaway
This Reddit case revealed some crucial insights into the IME and ESP relationship. By identifying how TrackingPoliciesCreated and FirstSync influence the IME’s GetEspPhase function, we saw firsthand how a few registry adjustments can unlock devices stuck in AccountSetup. It’s a reminder that understanding these internals is key to troubleshooting Intune issues efficiently.
Are you curious to try it yourself? In this additional blog, we’ll explore the scripts for checking IsSyncDone, TrackingPoliciesCreated, and more!