Today I’m sharing a useful bit of PowerShell I gracelessly punt from script to script whenever I need to make sure a prerequisite it met before running something and to keep checking until it’s met, then run what I need: “do X when Y is ready and keep checking Y until it’s ready”.

The original use for this was my script to create a new Microsoft 365 user, but hold off on some parts of it - such as time zone settings - until the Exchange Online mailbox is provisioned.  That takes some time, so I wanted to keep checking and as soon as I could, continue the script.

Another scenario this could potentially be used is if you have to execute something with a dependency to connectivity to a remote server, but you need to wait on a connection being established, e.g. VPN connection separate to the script.

Here’s what it looks like using my “don’t proceed until the mailbox exists” example:

if ((Get-Mailbox $email).PrimarySmtpAddress -eq $email) {
    [System.Windows.Forms.MessageBox]::Show("Mailbox provisioned in Exchange Online.")
    }
else {
    Do {
    Start-Countdown -Seconds 30 -Message 'Syncing to Azure AD and creating Office 365 mailbox.'
    }
    Until ((Get-Mailbox $email).PrimarySmtpAddress -eq $email)
    [System.Windows.Forms.MessageBox]::Show("Mailbox provisioned in Exchange Online.")
    }

I can hear some screaming in the distance at my use of MessageBox, but for everyone else: what’s happening here?

First, Get-Mailbox runs against the mailbox we are interested in setting.  It does not find the mailbox, so passes it to else, which says “I’ll wait a minute, then try again”, when until confirms the mailbox exists.  And repeat.  In your own use of checking the mailbox existed, all you’d need to do is change the variable of $email and the messages displayed.

I am also using Start-Countdown, an awesome function by Martin Pugh which is like Start-Sleep but with a visual countdown. Available here.

In another example, I only run the $install block if Test-Connection confirms I can connect to $server.  This one uses Start-Sleep instead of Start-Countdown and consequently, if it’s running interactively, the user will see error messages until the server’s available.  I use this when installing apps using PowerShell running as SYSTEM.  For example, run at startup but only when the VPN’s connected.

if (Test-Connection "$Server" -Count 1 -TimeToLive 135){
    &$install
    }
else {
    Do {
    Start-Sleep -Seconds 30
    }
    Until (Test-Connection "$Server" -Count 1 -TimeToLive 135)
    &$install
    }

The template minus any example information is below, where Check-This presenents your cmdlet for a prerequisite, and Do-This is the cmdlet for your action.

if (Check-This){
    Do-This
    }
else {
    Do {
    Start-Sleep -Seconds 5
    }
    Until (Check-This)
    Do-This
    }