Waiting for successful Office 365 sync

I am working with an organization that creates Office 365 email accounts from the AD email field when creating a new account in AD. The account is not actually created in Office 365 until a successful Azure AD Connect sync is completed.

I want to make changes to the Office account once it is created, what is the best way to wait until a successful sync has occurred?

My first idea was to get the last sync and take the time away from 31 minutes, but if the sync fails the account will not be created.

$LastSync = ((Get-MsolCompanyInformation).LastDirSyncTime).TimeOfDay.TotalHours
$GST = ([System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId((Get-Date), 'Greenwich Standard Time')).TimeOfDay.TotalHours
Start-Sleep -Seconds ([Math]::Abs(31-[Math]::Abs($LastSync - $GST)*60))*60

I wouldn’t check for the sync I would check for the account you just created. If it’s there - continue your script. :man_shrugging:t4:

1 Like

That’s a great idea. Will this do the trick?

do {
  $MsolAccount = Get-MsolUser -UserPrincipalName $EmailAddress -ErrorAction:SilentlyContinue
} while ($null -eq $MsolAccount)

I’m not sure. I’d prefer to use proper error handling with a try-catch block

And I’d highly recommend to insert a reasonable pause with :point_up_2:t4:

You don’t need to query the azure AD every few milliseconds. :wink:

1 Like

I was thinking that this might be poking azure AD too aggressively lol.

This closer? lol

do {
    try {
        $MsolAccount = Get-MsolUser -UserPrincipalName $EmailAddress 
    } catch {
        Start-Sleep -Seconds 300
    }
} while ($null -eq $MsolAccount)

Actually not. You may (re-)read the help for try-catch. To work properly you need a terminating error. If the cmdlet you’re about to use does not throw a terminating error by default you have to force it with -ErrorAction Stop.

Regardless of that - instead of asking if something’s going to work, why don’t you just try it? Since you’re using only a “get” cmdlet you cannot break something!? :smirk:

1 Like

You’re quite right. Pretty limited on what I have access to atm. After making that post, I did drum up a quick example with a local user and was scratching my head why it wasn’t work. I added -ErrorAction:Stop and voila. Thank you for your help. I am going to go ahead and run with the below unless you have any further suggestions.

do {
    try {
        $MsolAccount = Get-MsolUser -UserPrincipalName $EmailAddress -ErrorAction:Stop 
    } catch {
        Start-Sleep -Seconds 300
    }
} while ($null -eq $MsolAccount)

You can run a sync yourself and then your wait time will be drastically reduced. On your ad sync server look for the command Start-AdSyncSyncCycle. The good thing about that cmdlet is you can invoke it remotely and there’s no “double hop” issue. I’d also recommend adding a timeout so your script doesn’t get stuck in the do loop in the event the sync never happens

2 Likes

I like the idea. Is there any risk in forcing the sync? If not, I am thinking something like this:

Sart-AdSyncSyncCycle -PolicyType Delta
$attempts = 0
do {
    try {
        $MsolAccount = Get-MsolUser -UserPrincipalName $EmailAddress -ErrorAction:Stop 
        $attempts++
    } catch {
        Start-Sleep -Seconds 300
    }
} while ($null -eq $MsolAccount -and $attempts -le 6)

I have no idea about your environment so I can’t say. I can say in many of my environments the worse I’ve seen is the occasional error when the sync was already in progress. I take a similar approach with multiple attempts until successful. I have a much longer timer after for waiting for the device to be available in office 365. Successful sync does not equal instantly available objects.

Thank you very much for the help. Between you and Olaf the how to the what is looking promising.