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


Comments (5)

  1. dkegg says:

    Good catch!  thanks for that, I've updated the code above.

  2. N P says:

    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>

  3. N P says:

    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…

  4. RM says:

    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.

  5. Tory Jamison says:

    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.

Skip to main content