Category Archives: Office 365

Exchange Online reconnect script v2

A few weeks ago I posted a script that would automatically, periodically, reconnect to Exchange Online. In field testing it would still prompt for credentials after 1-2 days, whatever I did.

So I took a different route and am now rewriting Microsofts’ module on the fly to no longer prompt for credentials. If you use below function to connect to Exchange Online, you should never receive reconnect prompts 🙂

disclaimer: don’t overwrite $o365Creds with invalid creds elsewhere in your script as those are used globally.

function buildResilientExchangeOnlineSession {
    Write-Verbose "Connecting to Exchange Online"
    Set-Variable -Scope Global -Name o365Creds -Value $o365Creds -Force
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri -Credential $o365Creds -Authentication Basic -AllowRedirection
    Import-PSSession $Session -AllowClobber -DisableNameChecking
    Write-Verbose "Connected to Exchange Online, exporting module..."
    $temporaryModulePath = (Join-Path $Env:TEMP -ChildPath "temporaryEXOModule")
    $res = Export-PSSession -Session $Session -CommandName * -OutputModule $temporaryModulePath -AllowClobber -Force
    $temporaryModulePath = Join-Path $temporaryModulePath -ChildPath "temporaryEXOModule.psm1"
    Write-Verbose "Rewriting Exchange Online module, please wait a few minutes..."
    $found = $False
    (Get-Content $temporaryModulePath) | % {
        if(!$found -and $_.IndexOf("host.UI.PromptForCredential(") -ge 0){
            $line = "-Credential `$global:o365Creds ``"
                $found = $True
            $newContent += $line
            $newContent += $_
        $newContent += "`r`n"
    $newContent | Out-File -FilePath $temporaryModulePath -Force -Confirm:$False -ErrorAction Stop
    $Session | Remove-PSSession -Confirm:$False
    Write-Verbose "Module rewritten, re-importing..."
        Import-Module -Name $temporaryModulePath -Prefix $commandPrefix -DisableNameChecking -WarningAction SilentlyContinue -Force
        Write-Verbose "Module imported, you may now use all Exchange Online commands using $commandPrefix as prefix"
        Import-Module -Name $temporaryModulePath -DisableNameChecking -WarningAction SilentlyContinue -Force
        Write-Verbose "Module imported, you may now use all Exchange Online commands"
    return $temporaryModulePath



Public Folder to Office 365 Groups Migration Script

Earlier, I wrote on a new technet article that details migration to Office 365 groups from on prem public folders. Actually walking through that I noticed some inconveniences I figured I could improve on with a script. The main one being that the endpoint in Office 365 only supports a single Public Folder, excluding child folders.

So I wrote up a script (with resume support) that will map your Public Folders to O365 Groups and migrate them in as many batches as are required, fully automated.

You’ll end up with a nice csv file with all the details. Note:

  1. this script expects you to know what you’re doing!
  2. only tested with Exchange 2010 as source
  3. everything on prem is left untouched
  4. groups are not mail enabled, and security settings are not copied
  5. contacts are not copied
  6. make sure you read the code/in-script instructions between line 1 and line 48, and then if you’re curious, from line 71720

update 05/01: improved the connection status check + reconnect for remote ExO and fixed report file path auto generation

update 11/01: moved everything to start-job so exchange sessions are always isolated (no prompting after 1-2 days) and added total migration overview display 

update 25/01: exported the remote exchange module and added it as inline code with a modification so it won’t prompt for credentials, nothing else seems to otherwise prevent such prompts. This means the module may not match Microsoft’s if they update Exchange Online. Let me know if that causes issues for you or re-create it yourself with export-pssession and replace.

Migrating Public Folders to Office 365 Groups

Recently, I stumbled upon an article detailing how to migrate on-premises (or online) Public Folders to Office 365 Groups

Of course I had to try that out asap 🙂 I used an older script to make a report of my on prem public folders to pick one below 50GB.

It was mostly a breeze and the interface of Office 365 groups allows users to easily search and administer their old Public Folders. We purposely only use them for archive access, where the IM team manages access to the groups holding PF data. I can really recommend this strategy, especially if you can easily split them up in under 50GB sized groups.

I did have one slight error you may run into:

“MigrationTransientException: Couldn‎’t find a request that matches the information provided. Reason: No such request exists in the specified index. –> Couldn‎’t find a request that matches the information provided. Reason: No such request exists in the specified index. “

Reason for this: The source public folder path is incorrect, make sure your CSV is mapped correctly or your batch will spin forever (or at least longer than I had patience), never completing.



Provisioning Exchange Online / Office 365 Custom Roles automatically from Okta

Natively, when connected to Office 365, Okta allows you to automatically provision users and/or groups. Additionally, Okta will assign licenses you select, and if configured, set predefined roles in Office 365. This means you have one locus of control, very nice.

Then, Exchange Online allows you to define custom roles where you can scope permissions for your users with far greater granularity compared to the default roles, Okta won’t detect or provision users into these custom roles.

As this was a business requirement for a customer, I coded up a small proof of concept you can schedule that will read membership of selected groups in Okta through the Okta API, then ensure that ONLY those members are in the matching role groups in Exchange Online.

Continue reading Provisioning Exchange Online / Office 365 Custom Roles automatically from Okta

OnedriveMapper v3.10 released!

Version 3.10 of OneDriveMapper has been released!

  • handle the new tile / prompt that appears in IE login mode where Microsoft no longer always redirects to the portal
  • Progress bar color is now a configurable option (cloud/non cloud)
  • alphabetic ordering of configs (cloud only)
  • Fixed auto update loop issue where auto update would break itself for subsequent updates.
  • When restarting self (switching auth mode or auto updating) properly hide the console if this was set

Important Auto Update Instructions

If you were using Auto-Update, DO NOT do so for this version. Use the MSI to replace the old version (see last fixed issue).

New Azure AD Signin experience

As some may have read, Microsoft is previewing a potentially disruptive change without advance notice. My tenants don’t yet display the new behavior so I cannot test if OnedriveMapper will be affected. I haven’t heard of any issues yet 🙂

Get the new version here

GroupSync v0.56 available!

Version 0.56 is out, changes since v0.50:

  • prevent running twice (if scheduled task hangs for some reason)
  • send email notification if logfile is locked
  • replace add-adgroupmember and remove-adgroupmember with set-adgroup because of a known bug in these commands
  • multi-delete protection
  • auto reconnect to Exchange Online when the connection times out + longer timeout
  • additional filtering method for groups: extensionAttribute2
    • If you want to use this instead of the displayName prefix filter, read up on how to switch

Get it here

Onedrive Files On Demand is finally coming!

I’ve been ‘mentioning’ it a few times here and there, wasn’t allowed to say too much….but now it is finally public, coming before the end of the year Onedrive will have a sync on demand feature, no longer requiring local storage on your device!

It will allow all of us OnedriveMapper users to switch to a fully supported Microsoft solution for Windows 10 users.

Quirky thing is, Windows 7 and 2008 / 2012 R2 are not in scope. Possibly another good one to vote on at uservoice 🙂