This content is part of the Essential Guide: The essential admin's guide to Office 365 PowerShell
Manage Learn to apply best practices and optimize your operations.

Assign Office 365 licenses quickly with PowerShell

With some help from PowerShell, IT administrators can see how many Office 365 licenses are available and dispense them to users quickly.

With just a few keystrokes, an IT administrator can manage Office 365 licenses with PowerShell.

Using PowerShell to assign Office 365 licenses can take less time than navigating through the Office 365 admin center, particularly when a large number of users need to join the system as quickly as possible. Use commands and scripts to see which users are and aren't licensed, then assign licenses where needed.

To manage Office 365 licenses in PowerShell, first install the Azure Active Directory PowerShell module and the Microsoft Online Services Sign-In Assistant. When those applications are installed, run the following script to connect:
 Connect-MSOLService -Credential (Get-Credential)

How to issue basic commands

Some common licensing tasks for Office 365 administrators include determining how many users are missing licenses, and then if any licenses are already available to distribute to those users.

To find out which users need Office 365 licenses, use this PowerShell command:

Get-MSOLUser -All -UnlicensedUsersOnly | Format-Table UserPrincipleName, DisplayName, isLicensed, UsageLocation

This command uses the UsageLocation property because we can only apply an Office 365 license to a user account when it has a proper UsageLocation code. Use the –All parameter to show all users, otherwise the command will return just the first 500 results -- which is a problem in a large organization.

Next, use the Get-MSOLAccountSKU cmdlet to see how many Office 365 licenses are available.

Get-MSOLAccountSKU | Format-Table AccountSKUID,ActiveUnits,WarningUnits,ConsumedUnits,@{L="Remaining";E={$_.ActiveUnits-$_.WarningUnits-$_.ConsumedUnits}}

The AccountSkuId property shows what type of Office 365 subscription is available. In our example, the AccountSkuId result is adambertram:ENTERPRISEPACK where ENTERPRISEPACK refers to the Office 365 Enterprise E3 plan.

To assign a single license to a named user, use this script:

Set-MsolUserLicense -UserPrincipalName [email protected] -AddLicenses "adambertram:ENTERPRISEPACK"

That works for one user, but what if the administrator needs to roll out Office 365 to entire departments? The script below finds unlicensed users by department and assigns a license.

Get-MSOLUser -Department Developers -UnlicensedUsersOnly -All | Foreach-Object{Set-MSOLUserLicense -AddLicenses "adambertram:ENTERPRISEPACK" -ObjectID $_.ObjectID}

More advanced PowerShell techniques

In a perfect world, administrators could target users who need Office 365 licenses by their account properties, but most employees typically get an Office 365 license because someone asked their manager for one. With that in mind, we can take an arbitrary list of users and assign licenses to them. You may just have a text file with a list of users defined by email addresses; for the sake of simplicity, assume the email matches the UserPrincipalName. This script will apply an Office 365 license to the users in that text file:

Get-Content C:\UserList.txt | Foreach-object{Set-MSOLUserLicence -UserPrincipalName $_ -AddLicenses "adambertram:ENTERPRISEPACK"}

Scenarios may occur where the company hires many new people or acquires another organization. Most administrators won't want to add these users to the company and then license them in two separate steps. With help from human resources, get a comma-separated values (CSV) file with certain headers and get this done with a simple script.  

To illustrate this task, I've created a CSV file with the following header row: DisplayName, UserPrincipalName, City, Country, Department, FirstName, LastName, State, Title and UsageLocation. Use the script below to set up the users from that file:

Import-CSV C:\Users\username\Documents\UserList.txt |
Foreach-Object{New-MSOLUser -DisplayName $_.DisplayName '
-UserPrincipalName $_.UserPrincipalName '
-City $_.City '
-Country $_.Country '
-Department $_.Department '
-FirstName $_.FirstName '
-LastName $_.LastName '
-State $_.State '
-Title $_.Title '
-UsageLocation $_.UsageLocation '
-LicenseAssignment "adambertram:ENTERPRISEPACK" '
-Password "PleaseChangeM3!" '

While helpful, the script is repetitious. It's not hard to read, but we can refine it. For those who wondering why it specifies both Country and UsageLocation when typically they will match, there's a good reason for that. That bit of knowledge will also help us clean the script.

The Microsoft Developer Network page for New-MSOLUser shows all the parameters we can take from the pipeline by passing in an object with the correct property names. Import-CSV creates the object, so there is no need to specify all those parameters. We can do the same thing with the script below:

Import-CSV C:\Users\username\Documents\UserList.txt |
New-MSOLUser -Password "PleaseChangeM3!" '
-PasswordNeverExpires:$true '
-LicenseAssignment "adambertram:ENTERPRISEPACK"

You could add fields in the CSV for the –Password and the –LicenseAssignment parameters, but not the –PasswordNeverExpires parameter -- if you want to use that one at all. The reason is if you put "true" in the CSV file in the PasswordNeverExpires field, you won't end get a Boolean data type the cmdlet expects, but just a string that says true. You won't get an error, just a silent failure of that parameter. 

Next Steps

Understanding the different Office 365 plans for businesses

Three options to manage Office 365 user accounts

How to automate the creation of Active Directory user accounts

Dig Deeper on Office 365 and Microsoft SaaS setup and management