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
}