Patch My PC / Blog

Under the hood of the IME: The ESP Phases Explained!

by | Nov 1, 2024 | Blog

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.

Someone on reddit mentioning the fact that the Intune Management Extension is not processing the required applications uninstalls

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.

a snippet from the IME code showing the CheckDeviceAndAccountSetupStateWithWmi function

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.

a snippet from the IME code showing how it checks the sidecar csp status to determine if the device is still in the esp

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.

the appworkload.log showing the ime was stuck in the esp. It was stuck in the AccountSetup / User ESP

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.

A picture that shows the firstsync and its corrosponding issyncdone for user is missing

If the firstsync key is missing, the IME couldn’t confirm the initial user provisioning. (IsSyncDone)

a snippet from the IME code that show how it tries to get the logon if from the fist sync reigstry key to determine if the sync is done for the user

Besides the firstsync key totally missing, the persistent sidecar key also kept IME in “in ESP.”

somehow the policyprovider sidecar csp was also still on the device

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

After deleting the sidecar csp registry keys and rebooting the device, the IME was no longer stuck in the ESP

With the IME no longer thinking it was in the AccountPhase, the uninstalls started working.

after the reboot the IME started uninstalling the win32apps

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)

The ESPphase: Not In ESP, Device Preparation, Device Setup and Account Setup (User ESP)

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 and SkipUserStatusPage are set, meaning the ESP should be skipped.
  • Registry Path: HKLM\SOFTWARE\Microsoft\Enrollments\<GUID>\FirstSync\SkipDeviceStatusPage and SkipUserStatusPage
  • 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 and TrackingPoliciesCreated flags in Sidecar.
  • CSP Path: ./Vendor/MSFT/EnrollmentStatusTracking/DevicePreparation/PolicyProviders/Sidecar
  • Code Reference: EspHelper.GetHasProvisioningCompleted and GetSidecarTrackingPoliciesCreated
  • 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 PathValueExpected DataWhat if Missing?
Device-Level Provisioning Status
HKLM\SOFTWARE\Microsoft\Enrollments\<GUID>\FirstSync
ProvisioningStatus1 (Success)If missing, the device will not complete the DeviceSetup Phase in ESP and remain in the provisioning process.
IsSyncDone1 (Sync complete)If missing, ESP considers the provisioning incomplete and may retry or stall.
IsServerProvisioningDone1 (Server provisioning complete)If missing, ESP may interpret that server-side provisioning is still ongoing and may stay in the ESP flow.
HasProvisioningCompleted1 (Provisioning completed)If missing, ESP won’t exit as it assumes provisioning is not complete.
User-Specific Provisioning Status
HKLM\SOFTWARE\Microsoft\Enrollments\<GUID>\FirstSync\<UserSID>
IsSyncDone1 (Sync complete for user)Without this, ESP may keep the device in the AccountSetup Phase waiting for user-specific provisioning to complete.
HasProvisioningCompleted1 (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
SkipDeviceStatusPage1 (Skip)If both this and SkipUserStatusPage are 1, ESP will be bypassed and the device exits as NotInEsp.
SkipUserStatusPage1 (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
InstallationState3 (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!