Get DAG Mailboxes Faster with Start-Job

Have you ever needed to increase the speed of the get-mailbox cmdlet?   This Exchange PowerShell code is a building block that provides a way to get DAG mailboxes faster with start-job.  It will query the Database Availability Group within your Exchange organization and return all the mailbox databases.  Each mailbox database has an instance of get-mailbox run against it.

I’ve used the ForEach loop to process all mailbox databases individually and throttle how many jobs run at once.  This can be tuned to your liking and to the limits of what your environment can handle.  I’ve set the throttling to only run four jobs at a time in the code below.

The trick in this script is the IF and ELSE statements and the placement of the two start-job cmdlets.  The start-job cmdlet is necessary in the ELSE statement block otherwise the current pipeline object would get discarded before being processed once there are four jobs running.  Additionally, the wait-job -any cmdlet and switch will immediately start a new job when any currently running job is completed.

The very end of the script contains some cleanup code and uses the DO UNTIL statements to wait for all jobs to be completed before cleanup.  So just how much faster is this bit of code?  I’ve done a comparison between my code below and a single get-mailbox cmdlet that returns all mailboxes within the same DAG.

Get DAG Mailboxes Faster with Start-Job
Single Get-Mailbox cmdlet takes 10 minutes
Get DAG Mailboxes Faster with Start-Job
Start-Job takes three and a half minutes!

PowerGUI Script Editor

# Query all mailbox databases that are members of a DAG and that are not marked as
#  recovery databases.
$DAGDbs = Get-MailboxDatabase | Where-Object { $_.mastertype -eq "DatabaseAvailabilityGroup" -and $_.recovery -ne "true" }

# Use a Foreach loop to process each database.
ForEach ($DAGDb in $DAGDbs) {
	# Check the running status of jobs generated by this script to help throttle the
	#  concurrent jobs.
	$CheckJobs = Get-Job -Name GetMailboxes* | Where-Object { $_.State -eq 'Running' }
	# Use the If statement to throttle the number of concurrent jobs to four.
	if ($CheckJobs.count -le 3) {
		# When the number of running jobs is less than or equal to three, start
		#  another job using the DAG databases currently being processed within
		#  the ForEach loop.
		Start-Job -Name "GetMailboxes $DAGDb" -InitializationScript { Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 } `
		-ArgumentList ($ -ScriptBlock {
			Get-Mailbox -Database $Args[0] -ResultSize Unlimited
		# Process the else statement if more than four jobs are running.
	} else {
		# Check the jobs and wait until one of them finishes.  Then kick off
		#  another Start-Job.
		$CheckJobs | Wait-Job -Any
		# Start a job with the DAG database currently being processed.  This job
		#  ensures that the current pipeline object is not skipped.
		Start-Job -Name "GetMailboxes $DAGDb" -InitializationScript { Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 } `
		-ArgumentList ($ -ScriptBlock {
			Get-Mailbox -Database $Args[0] -ResultSize unlimited

# Dump all the jobs from this script into the $Mailboxes variable.
$Mailboxes = Get-Job -Name GetMailboxes* | Receive-Job
# Clean up the jobs from this session.
do {
	$CheckJobs = Get-Job -Name GetMailboxes* | Where-Object { $_.State -eq 'Running' }
} until ($CheckJobs -eq $null)

Get-Job -Name GetMailboxes* | Remove-Job



Leave a Comment