Managing licenses one user at a time in the Microsoft 365 admin center is fine for a few users, but when you need to add licenses to 50 employees or remove licenses from terminated contractors, PowerShell is your friend.
TL;DR
- Connect: Install-Module MSOnline; Connect-MsolService
- Add licenses: Set-MsolUserLicense -AddLicenses
- Remove licenses: Set-MsolUserLicense -RemoveLicenses
- Bulk operations: Use CSV files and ForEach loops
- Check usage: Get-MsolAccountSku for license availability
- Best practice: Test with -WhatIf first
Connect to Microsoft 365
First, you need the MSOnline module:
# Install if needed
Install-Module MSOnline
# Connect
Connect-MsolService
This opens a browser window for authentication. Use a global admin account.
Check Available Licenses
Before assigning licenses, know what you have:
Get-MsolAccountSku
This shows:
AccountSkuId ActiveUnits WarningUnits ConsumedUnits
------------ ----------- ------------ -------------
contoso:O365_BUSINESS_PREMIUM 100 0 87
The AccountSkuId is what you'll use in commands. For contoso, it would be "contoso:O365_BUSINESS_PREMIUM".
Add Licenses to Individual Users
Set-MsolUserLicense -UserPrincipalName "[email protected]" -AddLicenses "contoso:O365_BUSINESS_PREMIUM"
To add multiple licenses:
Set-MsolUserLicense -UserPrincipalName "[email protected]" -AddLicenses "contoso:O365_BUSINESS_PREMIUM","contoso:WINDOWS_STORE"
Remove Licenses from Users
Set-MsolUserLicense -UserPrincipalName "[email protected]" -RemoveLicenses "contoso:O365_BUSINESS_PREMIUM"
This removes the license but keeps the user account. If you want to remove all licenses:
$user = Get-MsolUser -UserPrincipalName "[email protected]"
$user.Licenses | ForEach-Object {Set-MsolUserLicense -UserPrincipalName $user.UserPrincipalName -RemoveLicenses $_.AccountSkuId}
Bulk License Operations
Create a CSV file with columns: UserPrincipalName, Action, LicenseSkuId
UserPrincipalName,Action,LicenseSkuId
[email protected],Add,contoso:O365_BUSINESS_PREMIUM
[email protected],Remove,contoso:O365_BUSINESS_PREMIUM
[email protected],Add,contoso:ENTERPRISEPACK
Then run:
$users = Import-Csv "C:\Temp\LicenseChanges.csv"
foreach ($user in $users) {
if ($user.Action -eq "Add") {
Set-MsolUserLicense -UserPrincipalName $user.UserPrincipalName -AddLicenses $user.LicenseSkuId
Write-Host "Added license $($user.LicenseSkuId) to $($user.UserPrincipalName)"
}
elseif ($user.Action -eq "Remove") {
Set-MsolUserLicense -UserPrincipalName $user.UserPrincipalName -RemoveLicenses $user.LicenseSkuId
Write-Host "Removed license $($user.LicenseSkuId) from $($user.UserPrincipalName)"
}
}
Replace Licenses (Upgrade/Downgrade)
To change from one license to another:
Set-MsolUserLicense -UserPrincipalName "[email protected]" -RemoveLicenses "contoso:O365_BUSINESS_PREMIUM" -AddLicenses "contoso:ENTERPRISEPACK"
This removes the old license and adds the new one in one command.
Check User License Status
Get-MsolUser -UserPrincipalName "[email protected]" | Select-Object DisplayName, Licenses
This shows what licenses the user has assigned.
Bulk Operations by Department/Group
Add licenses to all users in a department:
Get-MsolUser -All | Where-Object {$_.Department -eq "Sales"} | ForEach-Object {
Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -AddLicenses "contoso:O365_BUSINESS_PREMIUM"
}
License Reporting
Get a report of all licensed users:
Get-MsolUser -All | Where-Object {$_.isLicensed -eq $true} | Select-Object DisplayName, UserPrincipalName, Licenses | Export-Csv "C:\Temp\LicensedUsers.csv" -NoTypeInformation
Count licenses by type:
Get-MsolUser -All | Where-Object {$_.isLicensed -eq $true} | ForEach-Object {
$_.Licenses | ForEach-Object {
$_.AccountSkuId
}
} | Group-Object | Sort-Object Count -Descending
Common Issues and Solutions
Error: "The license assignment failed"
- Check if you have enough licenses available
- Verify the AccountSkuId is correct
- Make sure the user exists and isn't blocked
Error: "You cannot remove the last license from a user"
- Users must have at least one license to remain active
- If you want to deactivate a user, use Set-MsolUser -BlockCredential $true instead
Licenses not applying immediately
- Changes can take 5-15 minutes to propagate
- User may need to sign out and back in to Office apps
- Check the user's license status with Get-MsolUser
Best Practices
- Use -WhatIf first: Add -WhatIf to any Set-MsolUserLicense command to preview changes
- Work in batches: Don't try to license 1000 users at once; do 50-100 at a time
- Document changes: Keep a log of what licenses you assigned and when
- Check license usage: Monitor your license consumption regularly
- Use service accounts: Don't use your personal admin account for bulk operations
Quick Reference
# Connect
Connect-MsolService
# Check available licenses
Get-MsolAccountSku
# Add license to user
Set-MsolUserLicense -UserPrincipalName "[email protected]" -AddLicenses "tenant:LICENSE_SKU"
# Remove license from user
Set-MsolUserLicense -UserPrincipalName "[email protected]" -RemoveLicenses "tenant:LICENSE_SKU"
# Check user licenses
Get-MsolUser -UserPrincipalName "[email protected]" | Select-Object DisplayName, Licenses
# Bulk from CSV
$users = Import-Csv "licenses.csv"
$users | ForEach-Object {Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -AddLicenses $_.LicenseSkuId}
PowerShell license management saves hours when you have to make bulk changes. The admin center is fine for one-offs, but PowerShell is where the real efficiency lives.
Need Help with Microsoft 365 License Management?
License management, user provisioning, and Microsoft 365 administration can be complex. My company NHM Ohio provides comprehensive Microsoft 365 management services to keep your licensing efficient and cost-effective.
Whether you need license optimization, bulk user management, or ongoing administration, explore our Microsoft 365 services or contact us for assistance.