Auto-Licensing script for Office 365

You can use the following script with task scheduler to connect to your tenant via powershell, check for any unlicensed users and apply a license.

It will alert via email when the number of free licenses in your tenant falls below a certain number.

The script stores the credential password encrypted in a file, so be sure to run the script with the -setpassword switch and supply the login and password for the cloud user that has permissions to license mailboxes.   You’ll also need to modify the script to supply the user.

The -schedule switch creates a scheduled task for the script to run hourly. 

Be sure to update all the highlighted items to match your environment.

[Parameter(Position=0, Mandatory = $false, HelpMessage=”Creates ‘scheduled task’ in Windows Scheduler that can be adjusted in the future to perform synchronization cycle(s) at particular time interval”)]
[Switch] $Schedule,

[Parameter(Position=1, Mandatory = $false, HelpMessage=”Creates text file containing encrypted password”)]
[Switch] $Setpassword

# Switch to directory where script is located
pushd (split-path -parent $MyInvocation.MyCommand.Definition)

if ($Setpassword)
# If password needs to be re-saved, run: “./Autolicense.ps1 -Setpassword”
$cred = Get-Credential
$cred.Password | ConvertFrom-SecureString | Set-Content c:\o365\credmsol.txt
if ($schedule)
# If scheduled tasks needs to be recreated, run: “./Autolicense.ps1 -schedule”
$taskname = “O365 Auto Licensing Script”
schtasks.exe /create /sc HOURLY /MO 1 /st 06:00 /tn “$taskname” /tr “$PSHOME\powershell.exe -c ‘. ”$($myinvocation.mycommand.definition)”'”

$MsolAdmUser = “” 
$pwd = Get-Content c:\o365\credmsol.txt | ConvertTo-SecureString
$cred = New-Object System.Management.Automation.PSCredential $MsolAdmUser, $pwd

Import-Module MSOnline
Connect-MsolService -Credential $cred

$ActSku = Get-MsolAccountSku
$AvailableUnits = $ActSku.ActiveUnits – $ActSku.ConsumedUnits
if ($AvailableUnits -LE 99)
   Send-MailMessage -to -from -subject “Available Licenses has fallen below 100.” -smtpserver x.x.x.x

# get array of unlicensed users
$users = get-msoluser -UnlicensedUsersOnly
if (!($users)){write-host -fore Yellow “No unlicensed users”;exit}


foreach ($user in $users) 
   if ($AvailableUnits -gt 0)
   # Write-Host $user.UserPrincipalName
   Set-MsolUser -UserPrincipalName $user.UserPrincipalName -UsageLocation “US”
   Set-MsolUserLicense -UserPrincipalName $user.UserPrincipalName –AddLicenses $ActSku.AccountSkuId
   $O365UsrResult = Get-MsolUser -UserPrincipalName $user.UserPrincipalName
   if ($O365UsrResult.isLicensed -eq $true)
   #if ($O365UsrResult.isLicensed -eq $false)
     Write-Output $user.UserPrincipalName | Out-File c:\O365\AutoLicenseLog.txt -Append


Reader Comments

  1. There is a problem with this line…

    if (!($users){write-host -fore Yellow "No unlicensed users";exit}


    PS C:O365>     .Autolicense.ps1 -Setpassword

    Missing '(' after 'if' in if statement.

    At C:O365Autolicense.ps1:47 char:4

    + if  <<<< !($users){write-host -fore Yellow "No unlicensed users";exit}

       + CategoryInfo          : ParserError: (OpenParenToken:TokenId) [], ParseException

       + FullyQualifiedErrorId : MissingEndParenthesisInIfStatement

    PS C:O365>     .Autolicense.ps1 -Setpassword

    Unexpected token '{' in expression or statement.

    At C:O365Autolicense.ps1:47 char:15

    + if (!($users){ <<<< write-host -fore Yellow "No unlicensed users";exit}

       + CategoryInfo          : ParserError: ({:String) [], ParseException

       + FullyQualifiedErrorId : UnexpectedToken

    PS C:O365>

  2. It was missing a bracket 🙂

    if (!($users)){write-host -fore Yellow "No unlicensed users";exit}

    I already had this process working, albeit a little less clever… however my

    Connect-MsolService -Credential $cred

    line was hanging when run from the Scheduler! worked fine from command line. I'll try yours now…

  3. I’ve got two different types of licences for two categories of users, students and staff. Do you think there would be a way to sort those? Any help would be great.

  4. When you use get-msoluser you should include the -MaxResults parameter. Line 46 should be

    $users = get-msoluser -UnlicensedUsersOnly -MaxResults 500000

    If you need to license more than 100(?) users it will choke. 50K is the maximum amount of objects Azure AD can have a this time (7/23/2014) so 50K is a good value to set it at.

Leave a Reply

Your email address will not be published. Required fields are marked *