Scripting a Manual DirSync with PowerShell in Azure AD Connect v 1.1+

I had recently written a PowerShell script to manually kick off the DirSync Scheduled Task force changes I made in AD up to Office 365. It was easy, make sure the Scheduled Task isn't in a Running State (if it is, wait a bit and check again), kick off the scheduled task, then wait for it's State to change back to Ready. This solution worked great... until I upgraded to the latest Azure AD Connect client (version 1.1). Now the Scheduled Task was gone and I was left wondering how I was supposed to kick of the sync via PowerShell.

Searching around the Internet revealed that the new version replaced the Scheduled Task with AD Connect's own sync engine scheduling, controlled via PowerShell (YAY!). Since my script was already written in PowerShell this was going to make the process much easier, just run the new sync cmdlet (Start-ADSyncSyncCycle) and voila! But that was the easy part. The hard part was figuring out how to tell when the sync was running and when it finished, in the event of the rare chance it was already running when I tried to kick it off and risk my changes not being synced.

Nowhere in the sync scheduler (Get-ADSyncScheduler) did it say a current status and it didn't look like any new processes spawned. Digging through the event viewer I found an event with an ID of 904 and a message of "Scheduler::SchedulerThreadMain : Completed configured scheduler operations" that coincided with when it finished. Great! I know when it's done, but that event could still have correspond to a sync that was occurring when I tried to initiate another one. That was when a coworker asked me, "Well what happens if you try to run it while its already running?" "Well, umm. You see... I don't know. I didn't try it." So I kicked off a sync, then tried to kick off another right behind it. Lo and behold, an error saying it's already running! So all I needed to code was a try and catch and problem solved! Below is the code. Note that I am simply trying the Start-ADSyncSyncCycle cmdlet and catching for all errors. This could be refined a bit further to ensure the specific error received is that it is currently running and not a legit error preventing it from running.

Do{
#Try to start DirSync. If it is already running, we have to wait until it is done and kick it off again
$DirSyncRunning = $false
try{
Start-ADSyncSyncCycle
}
catch{
$DirSyncRunning = $true
Start-Sleep 10
}
} While($DirSyncRunning)

Start-Sleep 5

$DirSyncEvents = $false
$dirSyncStartTime = Get-Date
Do {
#Wait for our instance of DirSync to finish by monitoring for Event ID 904 in the logs with the message "Scheduler::SchedulerThreadMain : Completed configured scheduler operations." generated after we started
Start-Sleep 10
$DirSyncEvents = Get-EventLog -LogName Application -InstanceId 904 -Newest 1 -Message "Scheduler::SchedulerThreadMain : Completed configured scheduler operations." | ? {$_.TimeGenerated -gt $dirSyncStartTime}

} While(-not $DirSyncEvents)

Labels: , , , , , ,