As Exchange Admins, dealing with mailbox moves is something we do all the time. Checking the status of these moves is done in PowerShell but why not have the ability to view it in a Grid output using a simple script?

I have created a script with the columns I thought would be useful but you may find you want to show other information. The columns displayed in Grid are as follows:

  • DisplayName (Mailbox)
  • Status (Range of status messages, In Progress, Failed, Completed)
  • StatusDetail (Little more information than the previous Status info)
  • SyncStage (Stalled and many others)
  • TargetDatabase (where is the mailbox being moved to)
  • PercentComplete (how far along is the move, shows a number in percent)
  • LastFailure (Shows any failures, might be bad items limit etc.)

This is the output of the Grid when you run the script:

Exchange 2016/2019:- display the top 10 largest mailboxes

Click the refresh button, what this does is run the following line in PowerShell:

Get-MoveRequest | Get-MoveRequestStatistics | Select-Object DisplayName,Status,StatusDetail,SyncStage,TargetDatabase,PercentComplete 

This then populates the Grid as shown in the Figure below:

Exchange 2016/2019:- display the top 10 largest mailboxes

Below is the code used for all this, be sure to save it as a PS1 script and run it, for example, I called mine MailboxMoves.PS1. From the Exchange Management Shell (EMS), I use .\MailboxMoves.PS1

You can modify the code as you see fit, add or remove columns or change the Grid Size.

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# Create the form
$form = New-Object System.Windows.Forms.Form
$form.Text = "Mailbox Move Request Status"
$form.Size = New-Object System.Drawing.Size(650,650)
$form.StartPosition = "CenterScreen"

# Create a DataGridView to display mailbox moves
$dataGridView = New-Object System.Windows.Forms.DataGridView
$dataGridView.Size = New-Object System.Drawing.Size(600,500)
$dataGridView.Location = New-Object System.Drawing.Point(10,70)
$dataGridView.AutoSizeColumnsMode = [System.Windows.Forms.DataGridViewAutoSizeColumnsMode]::Fill

# Create columns for the DataGridView
$column1 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$column1.HeaderText = "DisplayName"
$column1.Name = "DisplayName"
$dataGridView.Columns.Add($column1)

$column2 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$column2.HeaderText = "Status"
$column2.Name = "Status"
$dataGridView.Columns.Add($column2)

$column3 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$column3.HeaderText = "StatusDetail"
$column3.Name = "StatusDetail"
$dataGridView.Columns.Add($column3)

$column4 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$column4.HeaderText = "SyncStage"
$column4.Name = "SyncStage"
$dataGridView.Columns.Add($column4)

$column5 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$column5.HeaderText = "TargetDatabase"
$column5.Name = "TargetDatabase"
$dataGridView.Columns.Add($column5)

$column6 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$column6.HeaderText = "PercentComplete"
$column6.Name = "PercentComplete"
$dataGridView.Columns.Add($column6)

$column7 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$column7.HeaderText = "LastFailure"
$column7.Name = "LastFailure"
$dataGridView.Columns.Add($column7)

# Function to populate the DataGridView with mailbox move data
function Get-MailboxMoveStatus {
    $moves =Get-MoveRequest | Get-MoveRequestStatistics | Select-Object DisplayName,Status,StatusDetail,SyncStage,TargetDatabase,PercentComplete # You can modify the filter as needed
    $dataGridView.Rows.Clear()

    foreach ($move in $moves) {
        $dataGridView.Rows.Add($move.DisplayName, $move.Status, $move.StatusDetail, $move.SyncStage, $move.TargetDatabase, $move.PercentComplete, $move.LastFailure)
    }
}

# Create a Refresh button to update the DataGridView
$refreshButton = New-Object System.Windows.Forms.Button
$refreshButton.Location = New-Object System.Drawing.Point(10,20)
$refreshButton.Size = New-Object System.Drawing.Size(80,30)
$refreshButton.Text = "Refresh"
$refreshButton.Add_Click({ Get-MailboxMoveStatus })

# Add controls to the form
$form.Controls.Add($dataGridView)
$form.Controls.Add($refreshButton)

# Set form event handler for initial loading
$form.Add_Load({ Get-MoveRequest | Get-MoveRequestStatistics | Select-Object DisplayName,Status,StatusDetail,SyncStage,TargetDatabase,PercentComplete })

# Show the form
[Windows.Forms.Application]::Run($form)

Additional Steps:

The form will be updated to include more buttons as follows:

  • Suspend Moves
  • Resume Moves
  • Set Bad Item Limits
  • Clear Move Requests

If you want anything else added, please reach out to me.

Hope it helps.

    wpChatIcon

    Discover more from Everything-PowerShell

    Subscribe now to keep reading and get access to the full archive.

    Continue reading