Bulk Custom Licensing Changes in Office 365 with PowerShell

Recently, I needed to make some very specific licensing changes to thousands of users in Office 365. There’s a lot of information out there on how to assign a license plan to a bunch of user accounts using PowerShell scripts, but I couldn’t find anything to set different plan services per user without running a script multiple times for each user, which kind of defeats the purpose.

To resolve this, I ended up creating a PowerShell script that will work for any company and any Office 365 subscription. Since I put so much time and effort into this PowerShell script, I wanted to share it with the world.

Generate a CSV File Template

The script must first be run with the GenerateCSVFile parameter, which will create a CSV file called “LicenseInfo.csv” in the same directory as the script.  The CSV file will contain headers for UserPrincipalName, UsageLocation, and then all available licensing plans & services in the currently logged into Office 365 tenant.

For more information about licensing plans & services, check out this TechNet article.

Update the CSV File

After generating the CSV template, you will need to add the User Principal Name of each Microsoft online user that needs to be licensed, or needs to have their licensing configuration changed.

For the rest of the fields in each row:

  • To add a single service in a license plan (e.g. Skype as part of E3), put a 1 in the field.
  • To add all services in a license plan (all E3 services), put a 1 in all fields for that license plan.
  • To remove a single service in a license plan (e.g. Skype as part of E3), put a 0 in the field.
  • To remove all services in a license plan (all E3 services), put a 0 in all fields for that license plan.
  • No action will be taken for any field that is left blank including the UsageLocation field.

Again, if you do not want to change the UsageLocation, or a license for a user, just leave the field blank.

Here’s an example screenshot:

Maintaining the CSV File

After generating the CSV file, do not modify the header names. The CSV file must contain the headers UserPrincipalName, UsageLocation, and the names of all services currently available in the tenant.  The naming convention used is PLANNAME:SERVICENAME.

For example, the Exchange service in the E3 Enterprise plan: ENTERPRISEPACK:EXCHANGE_S_ENTERPRISE

If new license plans or services are added to your tenant, you should regenerate a new CSV file, or manually add the new plans and/or services to the header row of an existing CSV file.

If needed, you can manually specify a different CSV file for use with the script by using the LicenseFilePath parameter, which could be useful if you wanted to keep separate CSV files for different tenants.

Logging & Error Handling

A log file will be created in the same directory as the script, and contains the same content that is displayed to the console window.

The script does not do checks for license compatibility, so if you try to enable two licenses that can’t be enabled at the same time (e.g. Standalone Skype and E3 Skype), one license will be enabled and an error will be thrown (but handled) while trying to enable the other.

Unfortunately, the error Microsoft returns for these kinds of issues is pretty generic, which make it very difficult to determine which licenses are not compatible with each other.

Final Thoughts

I’ve tested it the best I can, but I’m sure there are scenarios that I didn't consider. So, I encourage you to use a test account before using it with production users.

You can download the script from GitHub here: https://github.com/RadHaz75/License-O365Users/blob/master/License-O365Users.ps1