Mass migrations using Prepare-MoveRequest.ps1 – The Power of Powershell Part 1

I do not consider myself to be a PowerShell god, demi-god or even a Holy Half-Dead who has seen the Underverse (2 bonus points if you know where that came from!)  There are plenty of people who know PowerShell better than I do.  But, I have to admit that sometimes I get to the end of a task and I am amazed at what I was able to accomplish in PowerShell.

Today’s task looked like it could be a daunting one.  Here’s the situation:  3093 Exchange mailboxes that need to be migrated cross-forest.  FIM was used to create contact records in the destination forest, but they need to be converted to mail enabled user (MEU) objects to stage this move.  Plus, using FIM to create the MEUs is out of the picture in this case.  The contact items I have are the ones I am working with.

That means that I need to convert the users using the Prepare-MoveRequest.ps1 script.  Except there are literally over THREE THOUSAND.  And I also need to add new SMTP addresses, but we do not want a SMTP policy turned on for a few more weeks.  Having fun yet?  Last, for performance I need to scatter the moves across 3 MRSproxy servers (CAS Servers in the remote forest).

So, I turned to PowerShell to build the ultimate solution.

For starters, I needed to have a way to load the ~3100 users from a file and feed them into the prepare move script.  And I couldn’t just select contact objects, because they are not all coming.  I was given a list of users – by display name – that are being migrated.  So, I had to create a script to batch convert the 3100 contacts into mail enabled users.  It’s not elegant, but here’s what I created:


[powershell]$csvFile = Import-Csv -Path ‘C:\DisplayNames.csv’

ForEach ($row in $csvFile)
. .\Prepare-MoveRequest.ps1 -RemoteForestDomainController -RemoteForestCredential $RemoteCredentials -LocalForestDomainController -LocalForestCredential $LocalCredentials -LinkedMailUser -UseLocalObject -TargetMailUserOU FakeOU -Identity $row.DisplayName

In this script, we load each record out of the CSV and then call the move request.  A few important notes:  This is calling the second PS1 by using a DOT, SPACE, then the common .\  Second note – this script is in the same directory as the prepare-moverequest.ps1 or this method would not work.  I didn’t want a complex script so I placed this in the same directory.

I should also note that for auditing I wanted to be sure I captured ALL of the output of the Prepare-MoveRequest.ps1 script.  Anyone who has run it, knows it has a LOT of output.  I decided to use:

[sourcecode gutter="false"]Start-Transcript -path C:\output.txt -append[/sourcecode]

to ensure that I was capturing everything that was returned.  It is important to remember to issue the stop-transcript command when you are done.

In my next post I’ll outline how to batch add new SMTP email addresses that are created on the fly, without using an address policy.  Email address policies are the preferred method, for the record.  But this case required something outside of a normal process.

This entry was posted in Exchange 2010 and tagged , , , , . Bookmark the permalink. Both comments and trackbacks are currently closed.