Windows Autopilot

Improving the ESP duration

I talked about the behavior of the Windows MDM stack in a blog post about a year ago.  The quick recap:  When a device first enrolls in Intune, it will initiate an MDM sync (i.e. ask Intune to send a list of new policies, apps, certs, etc. that need to be process) every 3 minutes for 15 minutes, then every 15 minutes for two hours, then every 8 hours from that point onward.  There will also be an MDM sync when the user signs in (and there can be some additional ones too, sent to alert the MDM service about certain events, e.g. an LOB app install, but that’s a little outside of the scope of this conversation).

But my experience with this setup goes back almost a year and a half further (so 2.5 years total – yes, things can take a long time sometimes).  When investigating why the Windows Autopilot provisioning process was taking longer than expected, there was a gotcha:  It would typically take a second MDM sync before Intune would send the list of policies.  That’s no big deal for the device ESP, but it gets more interesting for user ESP.

Let’s look at an example scenario where you install a bunch of apps during device ESP.  What happens if that takes more than, say, 20 minutes?  Well, going back to the MDM sync interval, that would mean the every-three-minute syncs would have already completed, and now the MDM syncs would be occurring every 15 minutes instead of every three minutes.  And when the user signs in, a sync would be initiated right away and then the next one would occur between zero and 15 minutes later, so averaging about 7.5 minutes later.  What does the user see during this time?  All the user ESP (“Account setup”) categories will just stay at “Identifying” for that whole time:


What’s going on in the background?  Absolutely nothing, it’s just waiting for that next background MDM sync to happen.  (Imagine if it took more than 2 hours and 15 minutes for device ESP to finish.  Then the syncs would be running every 8 hours, so on average there would be a four hour delay.  Thankfully, most devices don’t take that long for device ESP to finish.)

Alright, so what can we do about this, to get rid of that extra wasted time?  We can do the MDM sync more frequently, like every three minutes, until Intune tells us that all policies have been received and no more are expected (at least until the next normal scheduled sync).  So we added code to ESP to do exactly that.  But that code was checked in after the release of Windows 10 version 2004, so that needed to be backported to the previous releases, where it is included in cumulative updates that you can install:

There can still be a little delay (half of three minutes on average, so 1.5 minutes), but that’s quite manageable in comparison.

Interestingly, this functionality addresses another challenge that wasn’t even something we had thought of at the time.  And “time” is exactly the right word here:  Let’s say a device boots up with the “wrong” time (e.g. the real-time clock in the PC is set to the right time, but the time zone of the OS doesn’t match) and then the time syncs (e.g. after a reboot with Hybrid Azure AD Join, when the device fixes its time via a time sync with an AD domain controller).  That sounds fairly harmless, but it has an odd side effect:  The MDM syncs that are run via scheduled tasks now don’t run, either because the time they have been configured for hasn’t arrived yet (time went backwards) or has already passed (time went forward).  But with the new ESP polling logic in place, we keep polling every 3 minutes regardless of what happens with the scheduled tasks, so everything keeps working fine.  So if you are seeing ESP timeouts that don’t make sense and logs show the time shifting around, make sure you have those cumulative updates preinstalled.

Categories: Windows Autopilot

6 replies »

  1. Thanks!

    Should we add something like the code below to for instance the AutopilotBranding script?

    # PREP: Install NuGet packageprovider and trust PSGallery
    if (-not (Get-PackageProvider -Name “NuGet” -ErrorAction SilentlyContinue)) {
    Write-Host “Installing NuGet package provider”
    Install-PackageProvider -Name “NuGet” -Force
    if ((Get-PSRepository -Name “PSGallery”).InstallationPolicy -ne “Trusted”) {
    Write-Host “Trusting PSGallery repository”
    Set-PSRepository -Name ‘PSGallery’ -InstallationPolicy Trusted

    # PREP: Grab current version and check for CU
    $requiredBuild = @{
    “2004” = [version]”19041.488″
    “1909” = [version]”18363.815″
    “1903” = [version]”18362.815″
    $productName = (Get-ItemProperty ‘HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion’ -Name ProductName).ProductName
    Try {
    $version = (Get-ItemProperty ‘HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion’ -Name ReleaseID -ErrorAction Stop).ReleaseID
    Catch {
    $version = “N/A”
    $currentBuild = (Get-ItemProperty ‘HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion’ -Name CurrentBuild).CurrentBuild
    $ubr = (Get-ItemProperty ‘HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion’ -Name UBR).UBR
    $osVersion = $currentBuild + “.” + $ubr
    $windowsVersion = @{ “Edition” = $productName; “Version” = $version; “Build” = [version]$osVersion }

    $cuInstalled = $true
    if ($windowsVersion.Build -lt $requiredBuild[$windowsVersion.Version]) { $cuInstalled = $false }
    Write-Host “Current Windows version info: $($windowsVersion.Edition) $($windowsVersion.Version), build $($windowsVersion.Build)”
    Write-Host “Required CU installed: $($cuInstalled)”

    # install latest CU if the required CU is missing
    if (-not $cuInstalled) {
    # make sure the PSWindowsUpdate module is available
    if (-not (Get-InstalledModule -Name “PSWindowsUpdate”-ErrorAction SilentlyContinue)) { Install-Module -Name “PSWindowsUpdate” }
    if (-not (Get-Module -Name “PSWindowsUpdate” -ListAvailable)) { Import-Module -Name “PSWindowsUpdate” }
    # install CU and SSU only
    Install-WindowsUpdate -Title “Servicing Stack Update” -AcceptAll -IgnoreReboot
    Install-WindowsUpdate -Title “Cumulative” -AcceptAll -IgnoreReboot


  2. Hey Michael,
    I am having an issue with the step Account Setup – Apps stuck on identifying until the ESP times out at 60 mins

    The issue only seems to occur when I add an extra app to be installed in the Device Step.
    I have 5 apps installing (Config Manager Client seems to be the one that causes the timeout).
    I’m not sure if this is an issue with the MDM syncs as I’m running Win10 1909 Pro with all the latest CU as of 2020-10.
    I pulled the logs after the timeout but not sure what i should be looking for sorry, and help would be greatly appreciated.


    • This is pretty much guaranteed to be caused by the ConfigMgr client. Once it installs, Intune won’t send any new policies, and since user ESP (account setup) is waiting for those policies (the ones that will never arrive) it will time out. Two workarounds: (1) disable user ESP (look for a blog that mentions doing that using a custom OMA-URI policy), or (2) target the ConfigMgr client to users instead of to machines so that it installs later in the process (once user ESP already knows what to track).