I can’t remember for certain, however, I would say since at least Exchange Server 2010 Hybrid, there was always the ability to complete a MoveRequest from on-premises to Exchange Online manually (via PowerShell) for a mailbox that was a within a migration batch. It’s really important for all customers to have this feature and something I have used on every enterprise migration to Exchange Online.

What are we trying to achive here?

With enterprise customers and the potential for thousands of mailboxes to move from on-premises to Exchange Online, business analyst’s get their “kind in a candy store” on and sift through data to come up with relationships between mailboxes so these mailboxes can be grouped together in migration batches for synchronised cutovers.

This is the tried and true method to ensure that not only business units, departments or teams cutover around the same timeframe, but, any specialised mailbox and shared mailbox relationships cutover. This then keeps business processes working nicely and with minimal disruption to users.

Sidebar – As of March 2016, it is now possible to have permissions to shared mailboxes cross organisations from cloud to on-premises, in hybrid deployments with Exchange Server 2013 or 2016 on-premises. Cloud mailboxes can access on-premises shared mailboxes which can streamline migrations where no all shared mailboxes need to be cutover with their full access users.

Reference: https://blogs.technet.microsoft.com/mconeill/2016/03/20/shared-mailboxes-in-exchange-hybrid-now-work-cross-premises/

How can we achieve this?

In the past and from what I had been doing for, what I feel is, the last 4 years, required one or two PowerShell cmdlets. The main reference that I’ve recently gone to is Paul Cunningham’s ExchangeServerPro blog post that conveniently is also the main Google search result. The two lines of PowerShell are as follows:

Step 1 – Change the Suspend When Ready to Complete switch to $false or turn it off

Get-MoveRequest mailbox@domain.com | Set-MoveRequest -SuspendWhenReadyToComplete:$false

Step 2 – Resume the move request to complete the cutover of the mailbox

Get-MoveRequest mailbox@domain.com | Resume-MoveRequest

Often I don’t even do step 1 mentioned above. I just resumed the move request. It all worked and go me the result I was after. This was across various migration projects with both Exchange Server 2010 and Exchange Server 2013 on-premises.

Things changed recently!?!? I’ve been working with a customer on their transition to Exchange Online for the last month and we’re now up to moving a pilot set of mailboxes to the cloud. Things were going great, as expected, nothing out of the ordinary. That is, until I wanted to cutover one initial mailbox in our first migration batch.

Why didn’t this work?

It’s been a few months, three quarters of a year, since I’ve done an Office 365 Exchange Online mail migration. I did the trusted Google and found Paul’s blog post. Had that “oh yeah, thats it” moment and remembered the PowerShell cmdlet’s. Our pilot user was cutover! Wrong..
The mailbox went from a status of “synced” to “incrementalsync” and back to “synced” with no success. I ran through the PowerShell again. No buono. Here’s a screen grab of what I was seeing.
SERIOUS FACE > Some names and identifying details have been changed to protect the privacy of individuals

And yes, that is my PowerShell colour theme. I have to get my “1337 h4x0r” going and make it green and stuff.

I see where this is going. There’s a work around. So Lucian, hurry up and tell me!

Yes, dear reader, you would be right. After a bit of back and forth with Microsoft, there is indeed a solution. It still involves two PowerShell cmdlet’s, but, there is two additional properties. One of those properties is actually hidden: -preventCompletion. The other property is a date and time value normally represented like: “28/11/2016 12:00:00 PM”.
Lets cut to the chase; here’s the two cmdlets”

Get-MoveRequest -Identity mailbox@domain.com | Set-MoveRequest -SuspendWhenReadyToComplete:$false -preventCompletion:$false -CompleteAfter 5
Get-MoveRequest -Identity mailbox@domain.com | Resume-MoveRequest

After running that, the mailbox, along with another four to be sure it worked, had all successfully cutover to Exchange Online. My -CompleteAfter value of “5” was meant to be 5 minutes. I would say that could be set with the correct date and time format and have the current date and time + 5minutes added to do it correctly. For me, it worked with the above PowerShell.

Final words

I know it’s been sometime since I moved mailboxes from on-premises to the cloud, however, it’s like riding a bike: you never forget. In this case, I knew the option was there to do it. I pestered Office 365 support for two days. I hope the awesome people there don’t hate me for it. Although, in the long run, it’s good that I did as figuring this out and using this method of manual mailbox cutover for sync’ed migration batches is crucial to any transition to the cloud.


Exchange, Office 365
, , , , , , ,

Join the conversation! 14 Comments

  1. great stuff

  2. This worked, Thanks a lot, I kept looking for a solution as to why my mailbox migrations to O365 were going from initial seeding back Synced after synching to 95% the first time, but were never completing after the running resume-moverequest.

  3. Good information. Thank you! However, I received the error below and the mailbox does not complete.
    StartAfter or CompleteAfter must not be set on requests using SuspendWhenReadyToComplete.
    I then tried running the cmdlet to only set the -SuspendWhenReadyToComplete flag to False and then ran it agin to set the -PrevenCompletion flag but it will not let me set the -PreventCompletion flag. It seems either this process is no longer valid or it matters how the migration batch is created.

    • Hi mate,
      The process might have changed. I worked through it with Microsoft Premier Support. If its changed, I’d suggest contacting Premier and working it through. Would be great if you shared the results!
      PS- Sorry, at the moment I’ve not got access to any O365/ExchangeOnline Hybrid tenants to test and validate.

  4. Hi Lucian,
    I have the same question as Paul does.
    I am unable to set the parameter CompleteAfter on my existing migration batches move requests. I was able to remove the Autosuspended and the PreventCompletion Flags from the individual mailbox move request.
    I have an environment with Exchange 2010 Sp3 as the backend and Hybrid Servers are Exchange 2013 CU10.
    Prashant Divakaran

    • Hi mate,
      The process might have changed. I worked through it with Microsoft Premier Support. If its changed, I’d suggest contacting Premier and working it through. Would be great if you shared the results!
      PS- Sorry, at the moment I’ve not got access to any O365/ExchangeOnline Hybrid tenants to test and validate.

  5. Hello Lucian,
    Thank you for the update. I will check with Microsoft and update you if this process has changed.

  6. Thanks Lucian for your help as it completely fixed my problem.
    This is what happened:-
    I run into an error: “SuspendWhenReadyToComplete and PreventCompletion flags cannot be specified on auto-resume jobs.”
    Followed your instructions :
    Get-MoveRequest -Identity mailbox@domain.com | Set-MoveRequest -SuspendWhenReadyToComplete:$false -preventCompletion:$false -CompleteAfter 5
    Get-MoveRequest -Identity mailbox@domain.com | Resume-MoveRequest
    The underlying move request went from initialseeding –>cleanup–>stalledduetotarget_database..–>Completed
    However replayed the migration batch – which said it was “Syncing” and eventually “failed” – even though in reality, the move request completed fine.
    o365 is funny sometimes!

  7. Hi Lucian,
    thanks for the tip, it worked perfectly in my case.
    I had a batch of mailboxes fully staged except one big mailbox still staging
    As I batch finalization option was not availlable, I used the commandlets you described.
    Something I noticed also, once I stopped the moverequest of the big mailbox that’s still staging,
    the finalize batch option became available although I did not use it.


  9. This has changed.
    I was able to complete individual patches using this:
    Set-MoveRequest -Identity “user1@contoso.com” -CompleteAfter (Get-Date)
    Resume-MoveRequest -Identity “user1@contoso.com”

  10. Saved Life

Comments are closed.