OnedriveMapper v2.50 released!

Version 2.50 of OneDriveMapper has been released!

  • Less ‘in your face’ progress display
  • timestamped logging
  • automatically prevent IE firstrun wizard from making the script hang
  • Powershell 2 friendly version check
  • also do SSO attempt at userlookupmode 1 and 2 if offered
  • Log errors if AADConnect Preview SSO is set

Get the new version here

Copy local AD contacts to O365

Recently I needed a basic method to copy over contacts from a local AD to O365, and in cases where a read-write contact already exists; update it. The scenario made sense, as we were working with multiple source AD’s where some had contacts of each other’s mail users, causing adsync conflicts. Thus we decided to take contacts out of ADsync scope and just copy them once.

The logic of the attached script is as follows:









Note that the script ONLY imports the displayname, primary and all secondary email addresses, and sets an extra X500 address for the legacy exchangeDN to avoid outlook cache hit misses.

If you need it, here’s a download link:


Powershell v1 and v2 friendly version of Invoke-WebRequest

If you need to use the Invoke-Webrequest on machines that are still running an older Powershell version, this function will help you out.

It sets a script-wide variable called ‘cookiejar’, which will persist any cookies during subsequent calls to this function. You can add customHeaders as a hashtable if you need to. By default the function will also attempt to respond to 401 challenges with the current user credentials.

function JosL-WebRequest{
    if($script:cookiejar -eq $Null){
        $script:cookiejar = New-Object System.Net.CookieContainer     
    $maxAttempts = 3
            $retVal = @{}
            $request = [System.Net.WebRequest]::Create($uri)
            $request.TimeOut = 5000
            $request.Method = $method
            if($trySSO -eq 1){
                $request.UseDefaultCredentials = $True
                $customHeaders.Keys | % { 
                    $request.Headers[$_] = $customHeaders.Item($_)
            $request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E)"
            $request.ContentType = "application/x-www-form-urlencoded"
            $request.CookieContainer = $script:cookiejar
            if($method -eq "POST"){
                $body = [byte[]][char[]]$body
                $upStream = $request.GetRequestStream()
                $upStream.Write($body, 0, $body.Length)
            $response = $request.GetResponse()
            $retVal.StatusCode = $response.StatusCode
            $retVal.StatusDescription = $response.StatusDescription
            $retVal.Headers = $response.Headers
            $stream = $response.GetResponseStream()
            $streamReader = [System.IO.StreamReader]($stream)
            $retVal.Content = $streamReader.ReadToEnd()
            return $retVal
            if($attempts -ge $maxAttempts){Throw}else{sleep -s 2}

O365GroupSync v0.43 available!

Version 0.43 is out, changes:

  • Better nesting of groups if they get created together (due to re-caching)
  • 3x faster performance during comparison of members in a full sync
  • .NET streamwriter vs Add-Content logging (to prevent missing log entries when the filesystem is slow)
  • Changed the differential switch to ‘do a differential’ instead of ‘do only a differential’
  • Added the full switch
  • Allow X500 proxy addresses to sync

Get it here

O365GroupSync v0.37 is out!

Version 0.37 is out, changes:

  • AD group selection filter
  • Automatic version check
  • Replaced Compare-Object to increase performance
  • Replaced searchExO function to increase performance loading groups from O365
  • Enhanced ExO caching (100+x faster)
  • Optionally ignore disabled accounts (parameter)
  • Categorised logging (| seperator in logfile)
  • Bugfixes

Get it here