Bulk provisioning Office 365 licenses and services script

By | February 7, 2016

Working with a client to ease the transition of Office 2010 (MSI) using KMS licensing to Office 2013/2016 (Click-to-Run) with subscription licensing to use the new Skype for Business client. It quickly became apparent that enabling thousands of globally dispersed users for a certain feature set via Office 365 Admin Portal wasn’t going to work. PowerShell always to the rescue!

Script Download: BulkO365LicenseServices.ps1 https://gallery.technet.microsoft.com/Bulk-provisioning-Office-f64747d5

First, we have some prerequisites to connect to Microsoft Online and Active Directory(AD) via PowerShell:

The following is a breakdown of the core logic in my script, minus the reporting, error handling and loops…

Load required modules and test connectivity.

Import-Module ActiveDirectory
Import-Module MSOnline
Connect-MsolService #Sign in using account with appropriate licensing permissions


Figure out the Account SKUs associated to the Office 365 Tenant, available licenses and the specific services to choose from. The most complete list I’ve found for the breakdown of services for each SKU can be found at: http://blogs.technet.com/b/treycarlee/archive/2013/11/01/list-of-powershell-licensing-sku-s-for-office-365.asp (don’t forget to check the comments).

Get-MsolAccountSku | %{$_.accountskuID;Write "Remaining Licenses:";($x =$_.ActiveUnits - $_.ConsumedUnits);$_.ServiceStatus|ft -hide}


It’s counterintuitive, but when applying specific Office 365 services from PowerShell you apply a list of services you want disabled vs. the services you want.

The easiest way to figure out which services to disable or enable is to configure a single account using the Office 365 Admin Portal and review via PowerShell.

Get-MsolUser -UserPrincipalName test2@lamontagnesolutions.com |%{ $_.licenses.servicestatus}


Make sure your licensing script takes into account when Microsoft changes or adds a new service. You’ll need a way of comparing enable services to available services, giving a disabled list.

#AccountSKU to use
#list of Enabled services
get-msolaccountsku | Where {$_.accountSkuID -eq $AccountSKUID } | Select -expand "ServiceStatus" | select -expand "ServicePlan" | select ServiceName | Where {$SubLicense -notcontains $_.ServiceName}


Grab users and additional attributes based on AD OU.

#User OU's distinguishedName attribute
$OUsearch = "DC=lamontagnesolutions,DC=com" 
get-aduser -Filter * -Searchbase $OUsearch -properties mail,Country| ?{ $_.Enabled -eq 'True'} |Ft name,userprincipalname,mail,country


Search for Microsoft Online user using either the mail or userprincipalname attribute as the cloud User Principal Name (UPN).

#Using user's Active Directory Mail attribute to find MSOl User. 
$upn = (get-aduser Test2 -Properties mail).mail
#To use UserPrincipalName instead to find MSOl User:
#$upn = (get-aduser Test2).UserPrincipalName
Get-MsolUser -UserPrincipalName $upn


Is the user licensed for the specific Account SKU?

Get-MsolUser -UserPrincipalName test2@lamontagnesolutions.com | ?{ $_.isLicensed -eq "TRUE" } | ?{ ($_.Licenses | ?{ $_.AccountSkuId -eq $AccountSKUID}).Length -gt 0}


If the user is already licensed for the specific Account SKU, confirm/enable required services. Don’t disable additional enabled services as these might be pilot users.

$disabledServices = (Get-MsolUser -UserPrincipalName test2@lamontagnesolutions.com).Licenses.servicestatus | where {$_.ProvisioningStatus -eq "Disabled"} | select -expand serviceplan | Select ServiceName
$disabledServices = $disabledServices | where {$SubLicense -notcontains $_.ServiceName}
$disabled = @()
foreach  ($item in $disabledServices.servicename) {$disabled += $item}
$LicenseOptions = New-MsolLicenseOptions -AccountSkuId $AccountSKUID -DisabledPlans $disabled
set-msoluserlicense  -userprincipalname test2@lamontagnesolutions.com -licenseoptions $LicenseOptions


If the user isn’t licensed, set location based on AD country attribute or manual country code then add Account SKU with required services.

$Location = (get-aduser Test1 -Properties country).country
#$Location = "CA"
$disabledServices = get-msolaccountsku | Where {$_.accountSkuID -eq $AccountSKUID } | Select -expand "ServiceStatus" | select -expand "ServicePlan" | select ServiceName | Where {$SubLicense -notcontains $_.ServiceName}
$disabled = @()
foreach  ($item in $disabledServices.servicename) {$disabled += $item}
$LicenseOptions = New-MsolLicenseOptions -AccountSkuId $AccountSKUID -DisabledPlans $Disabled
Set-MsolUser -UserPrincipalName test1@lamontagnesolutions.com –UsageLocation $Location
Set-MsolUserLicense -User test1@lamontagnesolutions.com -AddLicenses $AccountSKUID -LicenseOptions $LicenseOptions


Download: BulkO365LicenseServices.ps1 https://gallery.technet.microsoft.com/Bulk-provisioning-Office-f64747d5

4 thoughts on “Bulk provisioning Office 365 licenses and services script

  1. Pingback: Bulk provisioning Office 365 licenses and Services script | Real-Time UC | JC's Blog-O-Gibberish

    1. mlamontagne Post author

      I’ll always side with free 🙂 Interesting product though.

  2. David

    This script is very helpful. Is there a way to deactivate a particular license without affecting the rest?


Leave a Comment