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.
param
(
[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
exit
}
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)”'”
exit
}
$MsolAdmUser = “user@yourtenant.onmicrosoft.com”
$pwd = Get-Content c:\o365\credmsol.txt | ConvertTo-SecureString
$cred = New-Object System.Management.Automation.PSCredential $MsolAdmUser, $pwd
# CONNECT TO 365
Import-Module MSOnline
Connect-MsolService -Credential $cred
# RETRIEVE ACCOUNT INFORMATION
$ActSku = Get-MsolAccountSku
$AvailableUnits = $ActSku.ActiveUnits – $ActSku.ConsumedUnits
if ($AvailableUnits -LE 99)
{
Send-MailMessage -to recipient@domain.com -from server@domain.com -subject “Available Licenses has fallen below 100.” -smtpserver x.x.x.x
Exit
}
# get array of unlicensed users
$users = get-msoluser -UnlicensedUsersOnly
if (!($users)){write-host -fore Yellow “No unlicensed users”;exit}
# VERIFY IF USER IS ALREADY LICENSED
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
}
}
}
Good catch! thanks for that, I've updated the code above.
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>
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…
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.
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.