Wednesday, August 31, 2016

Script to Create Migration Batches

Migration batches are a nice feature introduced in Exchange 2013 for managing mailbox moves. In general they work pretty well, but it can be a bit awkward to work with batches in large organizations. The graphical interface only displays 500 mailboxes at a time and this can be limiting.

To get the batches exactly as you want them, you often end up exporting a list of mailboxes to a CSV file and then cutting that down into batches. You can create a batch by importing a CSV file.

To simplify this process, I've created a script that takes all the mailboxes from a list of source databases and generates the CSV files in batch sizes that you specify. For example, you can use both Admin1DB and Admin2DB as your source databases. If you specify a batch size of 200 mailboxes, then you'll get CSV files with 200 mailboxes except for the final CSV which has the left overs.

The script can also automatically create the migration batches if you turn that option on. In the script, you can specify one or more destination mailbox databases for the moves.

The script does not specify an archive database. If your users have archive mailboxes, then you'll need to edit the migration batches after creation and specify the correct databases for the archive mailboxes.

A final note: The script creates the migration batches, but does not start them. Starting the migration batches and the timing of it is up to you.

The script is below. I hope you find it useful.

 #This script selects users from existing source mailbox databases  
 #and creates migration batches to new Mailbox databases  
 #Typical use is migration projects, but could also be used for  
 #server retirement or cleaning up corrupted mailbox databases  
 #Multiple migration batches are created but you need to start them.  
 #Archive mailboxes are not included when the migration batches are  
 #created. To move archive mailboxes, edit the migration matches  
 #after they are created.  
 #Created by Byron Wright (@ByronWrightGeek)  
 #Set variables for creating batches  
 #BatchSize is the number of mailboxes in each batch  
 #BatchName is text added on to the CSV name and batch name  
 #This is useful to uniquely identify groups such as  
 #Admin or Students  
 #Path for CSV files  
 #This patch must already exist  
 #Mailboxes in the the source mailbox databases that are put into migration batches  
 #One or more databases can be used  
 $SourceMbxDB="Mailbox Database 0999986598","VIP Users"  
 #When $CreateMigrationBatch is $true a migration batch is created from  
 #each CSV file. If it is $false then only the CSV files are created.  
 #If $false then you don't need to configure the destination database  
 #Batches move mailboxes to the destination mailbox databases  
 #One or more databases can be specified  
 #When multiple databases are specified, the mailboxes are  
 #spread among the databases based on number of mailboxes and  
 #not size of mailboxes.  
 $DestinationDB="DB1","Mailbox Database 1840440945"  
 #Get list of mailboxes to move  
 Foreach ($s in $SourceMbxDB) {  
      $Mbx+=Get-Mailbox -Database $s  
 #Add a batch number property to each mailbox  
 #Add the EmailAddress property to each mailbox as required for the New-MigrationBatch CSV  
 Foreach ($m in $Mbx) {  
     $m | Add-Member -NotePropertyName Batch -NotePropertyValue $batch  
     $m | Add-Member -MemberType AliasProperty -Name EmailAddress -Value PrimarySMTPAddress  
 #CreateCSV files and migration batches  
 For($b=1;$b -le $TotalBatches;$b++) {  
      $mbx | Where-Object Batch -eq $b | Select-Object Name,EmailAddress,Batch | Export-CSV $BatchPath -NoTypeInformation   
      If ($CreateMigrationBatch -eq $true) {  
           New-MigrationBatch -Name $BatchFileName -CSVData ([System.IO.File]::ReadAllBytes(“$BatchPath”)) –Local –TargetDatabase $DestinationDB -AllowUnknownColumnsInCsv $true  


  1. Hello Wright,

    Thanks for the scripts. I am trying to run the scripts on a Exchange 2010 server and i get the below error message. How do i get this part to work on Exchange 2010.

    New-MigrationBatch : Cannot bind parameter 'Locale'. Cannot convert value "–TargetDatabase" to type
    "System.Globalization.CultureInfo". Error: "Culture is not supported.
    Parameter name: name
    –TargetDatabase is an invalid culture identifier."
    At line:70 char:108
    + ... “$BatchPath”)) –Local –TargetDatabase $DestinationDB -AllowUnknownColumnsInCsv $ ...
    + ~~~~~~
    + CategoryInfo : InvalidArgument: (:) [New-MigrationBatch], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.Exchange.Management.Migration.NewMigrationBatch

  2. New-MigrationBatch is not available in Exchange 2010. It only became available starting with Exchange Server 2013. So, if you're running it on Exchange 2010 that is likely the issue.

  3. I am new to scripting and migration. I am working on migrating 2,000 mailboxes from Exchange 2010 database to Exchange 2016 database. Do you have any similar script that can help create a batch and do the move automatically from Exchange 2010 to Exchange 2016 or any suggestion on how to accomplish these will be appreciated. Thanks.

  4. If you are moving from Exchange 2010 to Exchange 2016, you should be able to run that script on the Exchange 2016 server.

    Are you sure that you have the correct values in the script for the target database? What is your $TargetDB variable set to?

  5. You might need to move the migration mailbox first. This page shows how to move all of the arbitration mailboxes (including migration). See if completing that first helps.

  6. –TargetDatabase ($DestinationDB) was set to a DB on Exchange 2010 server. I will try this in my lab using a database that located in Exchange 2016 server.

  7. The scripts created all the batches for me how I wanted it but failed with the error message when initiating the New-MigrationBatch.

  8. Did you move the migration mailbox to Exchange 2016 yet? It will fail until that is done. It will be moved by using New-MoveRequest as per the link I supplied above.

  9. Thanks. I will do as suggested.