Windows 10

Forcing an MDM sync from a Windows 10 client

I was reading a blog recently that made me think “there’s got to be a better way” to force an MDM sync from the actual Windows 10 client – the example used the Graph API to connect from the client to the Intune service, then told Intune to initiate the sync, which sends a Windows notification (WNS push) to the client to tell it to wake up and do something.  Sure, it works, but you have to worry about security, Graph API throttling, etc.  I want something simple, typically for testing new stuff that I’ve set up, i.e. a new app or policy that I want to verify before going through a full Windows Autopilot deployment to find that I messed it up.

The investigation

I’ve spent some time looking at the mechanisms that are used by the MDM client in Windows 10 to do its stuff and was surprised to learn that it uses the Task Scheduler for all sync operations.  So if you go into the Intune portal and click Sync, the WNS push sent to the client is received and used to kick off one of those scheduled tasks.  If you go into Settings and click the Sync button:


It too kicks off one of those scheduled tasks.  So where are those scheduled tasks?  You’ll find them in the Task Scheduler tree under “Microsoft –> Windows –> EnterpriseMgmt –> <guid>” where that GUID value is the enrollment ID for the current (and only) MDM enrollment.  So doing this visually, it’s easy to find the folder:


And in there you’ll find a whole bunch of scheduled tasks.  Alright, so which one is called when?  Well, some are pretty obvious, like the one that runs when a user logs on.  And there are a few that are created after the MDM enrollment is first established:

  • “Schedule #1” runs every 3 minutes for the first 15 minutes.
  • “Schedule #2” runs every 15 minutes for two hours after that.
  • “Schedule #3” runs every 8 hours (which is why the device will only pick up new stuff every 8 hours unless notified by Intune via WNS).

But which ones are fired when when click the Sync button in Settings, and when you click the Sync link in the Intune portal?  Let’s try it and find out.  First, it’s useful to enable task scheduler execution history so that you can see when things are triggered or scheduled.  You can do this in the Task Scheduler UI using the “Enable All Tasks History” action:


As a test case, I then signed out and back in again to confirm that the “Login” scheduled task ran, and sure enough, I can see that it did:


(If you want to dig in even deeper, you can look in the “DeviceManagement-Enterprise-Diagnostics-Provider” event log to see the OMA-URI session being established and completed.)

OK, now let’s try to click the Sync button in Settings to see which scheduled task that runs.  Go to “Accounts –> Access work or school” then select the enrollment (“Connected to Contoso” in my case):


You can then click the Info button to get to the page I showed earlier with the Sync button.  Click the button and wait until the sync completes, then go back to the Task Scheduler to find which task ran.  You probably won’t be surprised to see that it’s the “Schedule to run OMADMClient by client” task:


(I ran it twice, which is why you see two sets of entries.) 

OK, now let’s do it from Intune:


And then check the Task Scheduler again.  If you guessed “Schedule to run OMADMClient by server” you would be wrong.  Instead, you can see two tasks run.  First, the “PushLaunch” task started:


And then the “Schedule to run OMADMClient by client” task was again triggered. 


Alright, we’ve proved that the “Schedule to run OMADMClient by client” task is always the one that does the sync.  Enough investigation, let’s do something more useful.

The scripting

It would seem that there is a choice:  You could kick off either the “PushLaunch” task or the “Schedule to run OMADMClient by client” tasks to kick off a sync.  PowerShell has a good ScheduledTasks module with a “Get-ScheduledTask” cmdlet.  Starting off simple, let’s just get a list of scheduled tasks by running that cmdlet with no parameters at all.  If you do that, you’ll see a few EnterpriseMgmt tasks:

\Microsoft\Windows\EnterpriseMgmt\C8B79BA8-… PushLaunch                        Ready
\Microsoft\Windows\EnterpriseMgmt\C8B79BA8-… PushRenewal                       Ready
\Microsoft\Windows\EnterpriseMgmt\C8B79BA8-… PushUpgrade                       Ready
\Microsoft\Windows\EnterpriseMgmt\Enterpris… Enterprise data protection enf… Ready

Alright, I guess the decision is made – the other tasks are hidden from the cmdlet.  So, let’s see what happens if we try to run the “PushLaunch” scheduled task from an elevated PowerShell session with this one-liner:

Get-ScheduledTask | ? {$_.TaskName -eq ‘PushLaunch’} | Start-ScheduledTask

No errors:


So if you check the task scheduler history for both “PushLaunch” and “Schedule to run OMADMClient by client” you should see new entries for both.  Looks good for “PushLaunch”:


And for “Schedule to run OMADMClient by client”:


And just to make sure, let’s check the event log for that same time.  Sure enough, a session started:


And finished successfully:


So there you have it:  a multi-page blog post that culminates in a one-line PowerShell script.  The power of automation…

Categories: Windows 10

1 reply »

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s