Licence Management

O365 License Management, Using AD Groups

Previously, I wrote the following post about license management: https://365.oholics.net/office-365-licence-management/. This post relied on text files to hold the UPN of users who should have specific licenses.

I now have a new script the does that same task but uses AD groups to hold the licence entitlements. I have placed a copy of the script below.

One thing of note (a bug), that will be present in the previous script, is that of assigning a licence that is in conflict with an already applied license. This issue arose while testing this new script, notably for users who were being entitled to a Project licence.

During processing, I was seeing errors like “Conflicting Service Plans: SHAREPOINTWAC_EDU, SHAREPOINTWAC_EDU” and “Conflicting Service Plans: SHAREPOINTSTANDARD_EDU, SHAREPOINTENTERPRISE_EDU”. Where this part was present in both of the license collections – the one already applied and the project license that was to be applied.

The solution is messy, but does work.

First the “base” user licence “STANDARDWOFFPACK_FACULTY” must be removed, and then replaced by the same license, but with more disabled components – in this case EXCHANGE_S_STANDARD, SHAREPOINTSTANDARD_EDU and SHAREPOINTWAC_EDU. Once that is complete and verified, then try to apply the complete Project license.

If ($MEMBERS_PROJECTONLINE_PLAN_1_FACULTY.SamAccountName -Contains $AdUser.sAMAccountName -and $PROJECTONLINE_PLAN_1_FACULTY_Applied -ne "True")
{
#Setup the bits that we don't want, because they are already present in the Project license and will cause an error otherwise...
$DisabledPlans=@()
$DisabledPlans+="EXCHANGE_S_STANDARD"
$DisabledPlans+="SHAREPOINTSTANDARD_EDU"
$DisabledPlans+="SHAREPOINTWAC_EDU"
# Define the Licence options
$FacultyLicenseOptions = New-MsolLicenseOptions -AccountSkuId $STANDARDWOFFPACK_FACULTY -DisabledPlans $DisabledPlans
#
#First we need to remove the standard licence..... in order to remove SHAREPOINTSTANDARD_EDU and SHAREPOINTWAC_EDU, we'll add the bits that we want back in a mo'
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_FACULTY
Start-Sleep -s 30
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
#Now set the new licence in place
$CheckUser=Get-MSOLUser -UserPrincipalName $User.UserPrincipalName
$CheckLicenses=$CheckUser.Licenses
$CheckSKUIDs=$CheckLicenses.AccountSkuId
If ($CheckSKUIDs -NotContains $STANDARDWOFFPACK_FACULTY)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_FACULTY -LicenseOptions $FacultyLicenseOptions
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
# Then try putting the full Project licence in place
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesAdded += "PROJECTONLINE_PLAN_1_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}

The complete script is here:

$ErrorActionPreference = "Stop"
$Error.Clear()
#####################################################
# Function to generate mail content for licencing errors
Function MailBody
{
$Exception=$error[0].Exception.Message
$Command=$error[0].InvocationInfo.Line.Trim()
$StrBody="Error: $Exception `r`rUser: $UserPrincipalName `r`rCommand: $Command `r`r##########################################################################################`r`r"
$Error.Clear()
Return $strBody
}
#####################################################
$sig = @"
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct NativeCredential
{
public UInt32 Flags;
public CRED_TYPE Type;
public IntPtr TargetName;
public IntPtr Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public IntPtr CredentialBlob;
public UInt32 Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public IntPtr TargetAlias;
public IntPtr UserName;
internal static NativeCredential GetNativeCredential(Credential cred)
{
NativeCredential ncred = new NativeCredential();
ncred.AttributeCount = 0;
ncred.Attributes = IntPtr.Zero;
ncred.Comment = IntPtr.Zero;
ncred.TargetAlias = IntPtr.Zero;
ncred.Type = CRED_TYPE.GENERIC;
ncred.Persist = (UInt32)1;
ncred.CredentialBlobSize = (UInt32)cred.CredentialBlobSize;
ncred.TargetName = Marshal.StringToCoTaskMemUni(cred.TargetName);
ncred.CredentialBlob = Marshal.StringToCoTaskMemUni(cred.CredentialBlob);
ncred.UserName = Marshal.StringToCoTaskMemUni(System.Environment.UserName);
return ncred;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Credential
{
public UInt32 Flags;
public CRED_TYPE Type;
public string TargetName;
public string Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public string CredentialBlob;
public UInt32 Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public string TargetAlias;
public string UserName;
}
public enum CRED_TYPE : uint
{
GENERIC = 1,
DOMAIN_PASSWORD = 2,
DOMAIN_CERTIFICATE = 3,
DOMAIN_VISIBLE_PASSWORD = 4,
GENERIC_CERTIFICATE = 5,
DOMAIN_EXTENDED = 6,
MAXIMUM = 7, // Maximum supported cred type
MAXIMUM_EX = (MAXIMUM + 1000), // Allow new applications to run on old OSes
}
public class CriticalCredentialHandle : Microsoft.Win32.SafeHandles.CriticalHandleZeroOrMinusOneIsInvalid
{
public CriticalCredentialHandle(IntPtr preexistingHandle)
{
SetHandle(preexistingHandle);
}
public Credential GetCredential()
{
if (!IsInvalid)
{
NativeCredential ncred = (NativeCredential)Marshal.PtrToStructure(handle,
typeof(NativeCredential));
Credential cred = new Credential();
cred.CredentialBlobSize = ncred.CredentialBlobSize;
cred.CredentialBlob = Marshal.PtrToStringUni(ncred.CredentialBlob,
(int)ncred.CredentialBlobSize / 2);
cred.UserName = Marshal.PtrToStringUni(ncred.UserName);
cred.TargetName = Marshal.PtrToStringUni(ncred.TargetName`);
cred.TargetAlias = Marshal.PtrToStringUni(ncred.TargetAlias);
cred.Type = ncred.Type;
cred.Flags = ncred.Flags;
cred.Persist = ncred.Persist;
return cred;
}
else
{
throw new InvalidOperationException("Invalid CriticalHandle!");
}
}
override protected bool ReleaseHandle()
{
if (!IsInvalid)
{
CredFree(handle);
SetHandleAsInvalid();
return true;
}
return false;
}
}
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CredRead(string target, CRED_TYPE type, int reservedFlag, out IntPtr CredentialPtr);
[DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)]
public static extern bool CredFree([In] IntPtr cred);
"@
Add-Type -MemberDefinition $sig -Namespace "ADVAPI32" -Name 'Util'
$targetName = "LicenceManagment"
$nCredPtr= New-Object IntPtr
$success = [ADVAPI32.Util]::CredRead($targetName,1,0,[ref] $nCredPtr)
if($success){
$critCred = New-Object ADVAPI32.Util+CriticalCredentialHandle $nCredPtr
$cred = $critCred.GetCredential()
$UserName = $cred.UserName;
$Password = $cred.CredentialBlob;
$Password = ConvertTo-SecureString -String $Password -AsPlainText -Force
$objCreds = New-Object Management.Automation.PSCredential $UserName, $Password
}
############ Import modules and login to MSOL ############
If(@(Get-Module | ? { $_.Name -eq "MSOnline"}).Count -eq 0)
{
Import-Module MSOnline;
}
If(@(Get-Module | ? { $_.Name -eq "ActiveDirectory"}).Count -eq 0)
{
Import-Module ActiveDirectory;
}
Try
{
Connect-MsolService -Credential $objCreds
}
Catch [System.Exception]
{
Send-MailMessage -From admin@blah.com -To someadmin@blah.com -cc someotheradmin@blah.com -Subject "ERROR - License management Login Failed!" -Body $_.Exception.Message -SmtpServer smtp.blah.com
Write-Host $_.Exception.Message
Exit
}
############ Setup Variables ############
$dateFormat = "HH:mm:ss dd/MM/yyyy"
############ Setup logging file ############
$Logfile="C:\Office365-Scripts\Licencing\LicenceManagement.txt"
############ AD Groups containing whose users who should have individual Licenses ############
$MEMBERS_CRMSTANDARD=Get-ADGroupMember -Identity CRMSTANDARD_Users
$MEMBERS_INTUNE_A=Get-ADGroupMember -Identity INTUNE_A_Users
$MEMBERS_OFFICESUBSCRIPTION_FACULTY=Get-ADGroupMember -Identity OFFICESUBSCRIPTION_FACULTY_Users
$MEMBERS_OFFICESUBSCRIPTION_STUDENT=Get-ADGroupMember -Identity OFFICESUBSCRIPTION_STUDENT_Users
$MEMBERS_POWER_BI_STANDARD=Get-ADGroupMember -Identity POWER_BI_STANDARD_Users
$MEMBERS_PROJECTONLINE_PLAN_1_FACULTY=Get-ADGroupMember -Identity PROJECTONLINE_PLAN_1_FACULTY_Users
$MEMBERS_PROJECTONLINE_PLAN_1_STUDENT=Get-ADGroupMember -Identity PROJECTONLINE_PLAN_1_STUDENT_Users
######################## Standard Licencing ######################
$POWER_BI_STANDARD = "<YourTenancyName>:POWER_BI_STANDARD"
$CRMSTANDARD = "<YourTenancyName>:CRMSTANDARD"
$INTUNE_A = "<YourTenancyName>:INTUNE_A"
######################## Faculty Licensing #######################
$STANDARDWOFFPACK_FACULTY = "<YourTenancyName>:STANDARDWOFFPACK_FACULTY"
$OFFICESUBSCRIPTION_FACULTY = "<YourTenancyName>:OFFICESUBSCRIPTION_FACULTY"
$STANDARDWOFFPACK_IW_FACULTY = "<YourTenancyName>:STANDARDWOFFPACK_IW_FACULTY"
$PROJECTONLINE_PLAN_1_FACULTY ="<YourTenancyName>:PROJECTONLINE_PLAN_1_FACULTY"
######################## Student Licensing #######################
$STANDARDWOFFPACK_STUDENT = "<YourTenancyName>:STANDARDWOFFPACK_STUDENT"
$STANDARDWOFFPACK_IW_STUDENT = "<YourTenancyName>:STANDARDWOFFPACK_IW_STUDENT"
$PROJECTONLINE_PLAN_1_STUDENT = "<YourTenancyName>:PROJECTONLINE_PLAN_1_STUDENT"
$OFFICESUBSCRIPTION_STUDENT = "<YourTenancyName>:OFFICESUBSCRIPTION_STUDENT"
######################## Generic settings ########################
$DisabledPlans = "EXCHANGE_S_STANDARD"
$UsageLocation = "GB"
############ Define the two types of Licence option - Faculty and Student ############
$FacultyLicenseOptions = New-MsolLicenseOptions -AccountSkuId $STANDARDWOFFPACK_FACULTY -DisabledPlans $DisabledPlans
$StudentLicenseOptions = New-MsolLicenseOptions -AccountSkuId $STANDARDWOFFPACK_STUDENT -DisabledPlans $DisabledPlans
#
############ Get users and apply Licenses ############
#
############ Do the licenced users first ############
ForEach($User in (Get-MsolUser -all | where {$_.isLicensed -eq "True"}))
#ForEach($User in (Get-MsolUser -all | where {$_.UserPrincipalName -eq "someotheradmin@blah.com"}))
{
If($User.UserPrincipalName -notlike "*<YourTenancyName>.onmicrosoft.com" -and $User.UserPrincipalName -ne "DirSync@blah.com")
{
$AdUser=Get-ADUser -Filter {UserPrincipalName -eq $User.UserPrincipalName} -Properties extensionAttribute5, sAMAccountName
Try
{
$date = Get-Date -Format $dateFormat
$LoggingContent=$null
$Licenses=$null
$SKUIDs=$null
$STANDARDWOFFPACK_STUDENT_Applied=$null
$STANDARDWOFFPACK_FACULTY_Applied=$null
$PROJECTONLINE_PLAN_1_FACULTY_Applied=$null
$POWER_BI_STANDARD_Applied=$null
$CRMSTANDARD_Applied=$null
$INTUNE_A_Applied=$null
$OFFICESUBSCRIPTION_FACULTY_Applied=$null
$LicensesAdded=@()
$LicensesRemoved=@()
$Licenses=$User.Licenses
$SKUIDs=$Licenses.AccountSkuId
ForEach ($SKU in $SKUIDs)
{
If ($SKU -eq $STANDARDWOFFPACK_IW_FACULTY)
{
Try
{
##### These should not be used, so remove if found #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_IW_FACULTY
$LicensesRemoved += "STANDARDWOFFPACK_IW_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
##### But then we need to replace that with a "normal" O365 licence, plus Pro Plus #####
If ($AdUser.extensionAttribute5 -eq "Staff")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_FACULTY -LicenseOptions $FacultyLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_FACULTY"
##### Add user to the AD group - just for reference.... #####
Add-ADGroupMember -Identity STANDARDWOFFPACK_FACULTY_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesAdded += "OFFICESUBSCRIPTION_FACULTY"
##### Add user to the AD group to ensure that they licence is not subsequently removed.... #####
Add-ADGroupMember -Identity OFFICESUBSCRIPTION_FACULTY_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
Else
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_STUDENT -LicenseOptions $StudentLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_STUDENT"
##### Add user to the AD group - just for reference.... #####
Add-ADGroupMember -Identity STANDARDWOFFPACK_STUDENT_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesAdded += "OFFICESUBSCRIPTION_STUDENT"
##### Add user to the AD group to ensure that they licence is not subsequently removed.... #####
Add-ADGroupMember -Identity OFFICESUBSCRIPTION_STUDENT_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $STANDARDWOFFPACK_IW_STUDENT)
{
Try
{
##### These should not be used, so remove if found #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_IW_STUDENT
$LicensesRemoved += "STANDARDWOFFPACK_IW_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
##### But then we need to replace that with a "normal" O365 licence, plus Pro Plus #####
If ($AdUser.extensionAttribute5 -ne "Staff")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_STUDENT -LicenseOptions $StudentLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_STUDENT"
##### Add user to the AD group - just for reference.... #####
Add-ADGroupMember -Identity STANDARDWOFFPACK_STUDENT_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesAdded += "OFFICESUBSCRIPTION_STUDENT"
##### Add user to the AD group to ensure that they licence is not subsequently removed.... #####
Add-ADGroupMember -Identity OFFICESUBSCRIPTION_STUDENT_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
Else
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_FACULTY -LicenseOptions $FacultyLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_FACULTY"
##### Add user to the AD group - just for reference.... #####
Add-ADGroupMember -Identity STANDARDWOFFPACK_FACULTY_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesAdded += "OFFICESUBSCRIPTION_FACULTY"
##### Add user to the AD group to ensure that they licence is not subsequently removed.... #####
Add-ADGroupMember -Identity OFFICESUBSCRIPTION_FACULTY_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
##### Standard O365 Licenses #####
If ($SKU -eq $STANDARDWOFFPACK_STUDENT)
{
$STANDARDWOFFPACK_STUDENT_Applied="True"
If ($ADUser.extensionAttribute5 -eq "Staff")
{
Try
{
##### Remove Student licence from Staff member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_STUDENT
$LicensesRemoved += "STANDARDWOFFPACK_STUDENT"
##### Remove user from the AD group #####
Remove-ADGroupMember -Identity STANDARDWOFFPACK_STUDENT_Users -Members $AdUser.sAMAccountName -Confirm:$False
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Staff licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_FACULTY -LicenseOptions $FacultyLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_FACULTY"
##### Add user to the AD group - just for reference.... #####
Add-ADGroupMember -Identity STANDARDWOFFPACK_FACULTY_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $STANDARDWOFFPACK_FACULTY)
{
$STANDARDWOFFPACK_FACULTY_Applied="True"
If ($ADUser.extensionAttribute5 -ne "Staff")
{
Try
{
##### Remove Staff licence from Student member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_FACULTY
$LicensesRemoved += "STANDARDWOFFPACK_FACULTY"
##### Remove user from the AD group #####
Remove-ADGroupMember -Identity STANDARDWOFFPACK_FACULTY_Users -Members $AdUser.sAMAccountName -Confirm:$False
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Student licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_STUDENT -LicenseOptions $StudentLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_STUDENT"
##### Add user to the AD group - just for reference.... #####
Add-ADGroupMember -Identity STANDARDWOFFPACK_STUDENT_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
##### Individual Subscriptions #####
If ($SKU -eq $PROJECTONLINE_PLAN_1_FACULTY)
{
$PROJECTONLINE_PLAN_1_FACULTY_Applied="True"
If ($MEMBERS_PROJECTONLINE_PLAN_1_FACULTY.SamAccountName -NotContains $AdUser.sAMAccountName)
{
Try
{
#If the user is not in the group, then simply revoke the licence
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesRemoved += "PROJECTONLINE_PLAN_1_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
ElseIf ($ADUser.extensionAttribute5 -ne "Staff")
{
Try
{
##### Remove Staff licence from Student member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesRemoved += "PROJECTONLINE_PLAN_1_FACULTY"
##### Remove user from the AD group to ensure that the licence is not subsequently/ mistakenly added again.... #####
Remove-ADGroupMember -Identity PROJECTONLINE_PLAN_1_FACULTY_Users -Members $AdUser.sAMAccountName -Confirm:$False
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Student licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_STUDENT
$LicensesAdded += "PROJECTONLINE_PLAN_1_STUDENT"
##### Add user to the AD group to ensure that the licence is not subsequently removed.... #####
Add-ADGroupMember -Identity PROJECTONLINE_PLAN_1_STUDENT_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $PROJECTONLINE_PLAN_1_STUDENT)
{
$PROJECTONLINE_PLAN_1_STUDENT_Applied="True"
If ($MEMBERS_PROJECTONLINE_PLAN_1_STUDENT.SamAccountName -NotContains $AdUser.sAMAccountName)
{
Try
{
#If the user is not in the group, then simply revoke the licence
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $PROJECTONLINE_PLAN_1_STUDENT
$LicensesRemoved += "PROJECTONLINE_PLAN_1_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
ElseIf ($ADUser.extensionAttribute5 -eq "Staff")
{
Try
{
##### Remove Student licence from Staff member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $PROJECTONLINE_PLAN_1_STUDENT
$LicensesRemoved += "PROJECTONLINE_PLAN_1_STUDENT"
##### Remove user from the AD group to ensure that the licence is not subsequently/ mistakenly added again.... #####
Remove-ADGroupMember -Identity PROJECTONLINE_PLAN_1_STUDENT_Users -Members $AdUser.sAMAccountName -Confirm:$False
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Staff licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesAdded += "PROJECTONLINE_PLAN_1_FACULTY"
##### Add user to the AD group to ensure that the licence is not subsequently removed.... #####
Add-ADGroupMember -Identity PROJECTONLINE_PLAN_1_FACULTY_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $OFFICESUBSCRIPTION_FACULTY)
{
$OFFICESUBSCRIPTION_FACULTY_Applied="True"
If ($MEMBERS_OFFICESUBSCRIPTION_FACULTY.SamAccountName -NotContains $AdUser.sAMAccountName)
{
Try
{
#If the user is not in the group, then simply revoke the licence
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesRemoved += "OFFICESUBSCRIPTION_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
ElseIf ($ADUser.extensionAttribute5 -ne "Staff")
{
Try
{
##### Remove Staff licence from Student member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesRemoved += "OFFICESUBSCRIPTION_FACULTY"
##### Remove user from the AD group to ensure that the licence is not subsequently/ mistakenly added again.... #####
Remove-ADGroupMember -Identity OFFICESUBSCRIPTION_FACULTY_Users -Members $AdUser.sAMAccountName -Confirm:$False
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Student licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesAdded += "OFFICESUBSCRIPTION_STUDENT"
##### Add user to the AD group to ensure that the licence is not subsequently removed.... #####
Add-ADGroupMember -Identity OFFICESUBSCRIPTION_STUDENT_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $OFFICESUBSCRIPTION_STUDENT)
{
$OFFICESUBSCRIPTION_STUDENT_Applied="True"
If ($MEMBERS_OFFICESUBSCRIPTION_STUDENT.SamAccountName -NotContains $AdUser.sAMAccountName)
{
Try
{
#If the user is not in the group, then simply revoke the licence
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesRemoved += "OFFICESUBSCRIPTION_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
ElseIf ($ADUser.extensionAttribute5 -eq "Staff")
{
Try
{
##### Remove Student licence from Staff member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesRemoved += "OFFICESUBSCRIPTION_STUDENT"
##### Remove user from the AD group to ensure that the licence is not subsequently/ mistakenly added again.... #####
Remove-ADGroupMember -Identity OFFICESUBSCRIPTION_STUDENT_Users -Members $AdUser.sAMAccountName -Confirm:$False
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Staff licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesAdded += "OFFICESUBSCRIPTION_FACULTY"
##### Add user to the AD group to ensure that the licence is not subsequently removed.... #####
Add-ADGroupMember -Identity OFFICESUBSCRIPTION_FACULTY_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $POWER_BI_STANDARD)
{
$POWER_BI_STANDARD_Applied="True"
If ($MEMBERS_POWER_BI_STANDARD.SamAccountName -NotContains $AdUser.sAMAccountName)
{
Try
{
#If the user is not in the group, then simply revoke the licence
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $POWER_BI_STANDARD
$LicensesRemoved += "POWER_BI_STANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $CRMSTANDARD)
{
$CRMSTANDARD_Applied="True"
If ($MEMBERS_CRMSTANDARD.SamAccountName -NotContains $AdUser.sAMAccountName)
{
Try
{
#If the user is not in the group, then simply revoke the licence
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $CRMSTANDARD
$LicensesRemoved += "CRMSTANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $INTUNE_A)
{
$INTUNE_A_Applied="True"
If ($MEMBERS_INTUNE_A.SamAccountName -NotContains $AdUser.sAMAccountName)
{
Try
{
#If the user is not in the group, then simply revoke the licence
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $INTUNE_A
$LicensesRemoved += "INTUNE_A"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
}
}
Catch [System.Exception]
{
#Mop up any other errors
Send-MailMessage -From admin@blah.com -To someadmin@blah.com -cc someotheradmin@blah.com -Subject "ERROR - O365 Licence Management" -Body $_.Exception.Message -SmtpServer smtp.blah.com
Write-Host $_.Exception.Message
}
Try
{
##### Apply individual licences if they are not applied already #####
If ($MEMBERS_PROJECTONLINE_PLAN_1_FACULTY.SamAccountName -Contains $AdUser.sAMAccountName -and $PROJECTONLINE_PLAN_1_FACULTY_Applied -ne "True")
{
#Setup the bits that we don't want, because they are already present in the Project license and will cause an error otherwise...
$DisabledPlans=@()
$DisabledPlans+="EXCHANGE_S_STANDARD"
$DisabledPlans+="SHAREPOINTSTANDARD_EDU"
$DisabledPlans+="SHAREPOINTWAC_EDU"
# Define the Licence options
$FacultyLicenseOptions = New-MsolLicenseOptions -AccountSkuId $STANDARDWOFFPACK_FACULTY -DisabledPlans $DisabledPlans
#
#First we need to remove the standard licence..... in order to remove SHAREPOINTSTANDARD_EDU and SHAREPOINTWAC_EDU, we'll add the bits that we want back in a mo'
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_FACULTY
Start-Sleep -s 30
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
#Now set the new licence in place
$CheckUser=Get-MSOLUser -UserPrincipalName $User.UserPrincipalName
$CheckLicenses=$CheckUser.Licenses
$CheckSKUIDs=$CheckLicenses.AccountSkuId
If ($CheckSKUIDs -NotContains $STANDARDWOFFPACK_FACULTY)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_FACULTY -LicenseOptions $FacultyLicenseOptions
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
# Then try putting the full Project licence in place
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesAdded += "PROJECTONLINE_PLAN_1_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($MEMBERS_PROJECTONLINE_PLAN_1_STUDENT.SamAccountName -Contains $AdUser.sAMAccountName -and $PROJECTONLINE_PLAN_1_STUDENT_Applied -ne "True")
{
#Setup the bits that we don't want, because they are already present in the Project license and will cause an error otherwise...
$DisabledPlans=@()
$DisabledPlans+="EXCHANGE_S_STANDARD"
$DisabledPlans+="SHAREPOINTSTANDARD_EDU"
$DisabledPlans+="SHAREPOINTWAC_EDU"
# Define the Licence options
$StudentLicenseOptions = New-MsolLicenseOptions -AccountSkuId $STANDARDWOFFPACK_STUDENT -DisabledPlans $DisabledPlans
#
#First we need to remove the standard licence..... in order to remove SHAREPOINTSTANDARD_EDU and SHAREPOINTWAC_EDU, we'll add the bits that we want back in a mo'
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_STUDENT
Start-Sleep -s 30
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
#Now set the new licence in place
$CheckUser=Get-MSOLUser -UserPrincipalName $User.UserPrincipalName
$CheckLicenses=$CheckUser.Licenses
$CheckSKUIDs=$CheckLicenses.AccountSkuId
If ($CheckSKUIDs -NotContains $STANDARDWOFFPACK_STUDENT)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_STUDENT -LicenseOptions $StudentLicenseOptions
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
# Then try putting the full Project licence in place
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_STUDENT
$LicensesAdded += "PROJECTONLINE_PLAN_1_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($MEMBERS_POWER_BI_STANDARD.SamAccountName -Contains $AdUser.sAMAccountName -and $POWER_BI_STANDARD_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $POWER_BI_STANDARD
$LicensesAdded += "POWER_BI_STANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($MEMBERS_CRMSTANDARD.SamAccountName -Contains $AdUser.sAMAccountName -and $CRMSTANDARD_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $CRMSTANDARD
$LicensesAdded += "CRMSTANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($MEMBERS_INTUNE_A.SamAccountName -Contains $AdUser.sAMAccountName -and $INTUNE_A_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $INTUNE_A
$LicensesAdded += "INTUNE_A"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($MEMBERS_OFFICESUBSCRIPTION_FACULTY.SamAccountName -Contains $AdUser.sAMAccountName -and $OFFICESUBSCRIPTION_FACULTY_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesAdded += "OFFICESUBSCRIPTION_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($MEMBERS_OFFICESUBSCRIPTION_STUDENT.SamAccountName -Contains $AdUser.sAMAccountName -and $OFFICESUBSCRIPTION_STUDENT_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesAdded += "OFFICESUBSCRIPTION_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
Catch [System.Exception]
{
#Mop up any other errors
Send-MailMessage -From admin@blah.com -To someadmin@blah.com -cc someotheradmin@blah.com -Subject "ERROR - O365 Licence Management" -Body $_.Exception.Message -SmtpServer smtp.blah.com
Write-Host $_.Exception.Message
}
#Reporting bits:
If ($LicensesAdded.Count -eq 0 -and $LicensesRemoved.Count -gt 0)
{
$LoggingContent=$Date + ",User," + $User.UserPrincipalName + ",LicensesRemoved," + ($LicensesRemoved -join ',')
}
If ($LicensesAdded.Count -gt 0 -and $LicensesRemoved.Count -eq 0)
{
$LoggingContent=$Date + ",User," + $User.UserPrincipalName + ",Licenses Added," + ($LicensesAdded -join ',')
}
If ($LicensesAdded.Count -gt 0 -and $LicensesRemoved.Count -gt 0)
{
$LoggingContent=$Date + ",User," + $User.UserPrincipalName + ",Licenses Added," + ($LicensesAdded -join ',') + ",LicensesRemoved," + ($LicensesRemoved -join ',')
}
# Write out the log
Add-Content $Logfile $LoggingContent
# If any errors occurred adding or removing icences - the variable $strMailBody will have some content, so send it to admins...
If ($strMailBody -ne $null)
{
Send-MailMessage -From admin@blah.com -To someadmin@blah.com -cc someotheradmin@blah.com -Subject "ERROR - O365 Licence Management" -Body $strMailBody -SmtpServer smtp.blah.com
Write-Host $strMailBody
}
}
}
############ Now mop up the unlicenced users ############
ForEach($User in (Get-MsolUser -all | where{$_.isLicensed -ne "True"}))
{
If($User.UserPrincipalName -notlike "*<YourTenancyName>.onmicrosoft.com" -and $User.UserPrincipalName -ne "DirSync@blah.com")
{
$date = Get-Date -Format $dateFormat
$LoggingContent=$null
$LicensesAdded=@()
$AdUser=Get-ADUser -Filter {UserPrincipalName -eq $User.UserPrincipalName} -Properties extensionAttribute5, sAMAccountName
Try
{
If ($ADUser.extensionAttribute5 -eq "Staff")
{
Try
{
# Set usage location
Set-MsolUser -UserPrincipalName $User.UserPrincipalName -UsageLocation $UsageLocation
}
Catch [System.Exception]
{
$strBody="Error setting UsageLocation for $User.UserPrincipalName"
$strMailBody=$strMailBody+$strBody
}
Try
{
# Set standard O365 licence without Exchange
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_FACULTY -LicenseOptions $FacultyLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_FACULTY"
##### Add user to the AD group - just for reference.... #####
Add-ADGroupMember -Identity STANDARDWOFFPACK_FACULTY_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($ADUser.extensionAttribute5 -ne "Staff")
{
Try
{
# Set usage location
Set-MsolUser -UserPrincipalName $User.UserPrincipalName -UsageLocation $UsageLocation
}
Catch [System.Exception]
{
$strBody="Error setting UsageLocation for $User.UserPrincipalName"
$strMailBody=$strMailBody+$strBody
}
Try
{
# Set standard O365 licence without Exchange
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_STUDENT -LicenseOptions $StudentLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_STUDENT"
##### Add user to the AD group - just for reference.... #####
Add-ADGroupMember -Identity STANDARDWOFFPACK_STUDENT_Users -Members $AdUser.sAMAccountName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
##### Individual Subscriptions for unlicenced users - unlikely to ever hit here... #####
If ($MEMBERS_PROJECTONLINE_PLAN_1_FACULTY.SamAccountName -Contains $AdUser.sAMAccountName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesAdded += "PROJECTONLINE_PLAN_1_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($MEMBERS_PROJECTONLINE_PLAN_1_STUDENT.SamAccountName -Contains $AdUser.sAMAccountName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_STUDENT
$LicensesAdded += "PROJECTONLINE_PLAN_1_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($MEMBERS_POWER_BI_STANDARD.SamAccountName -Contains $AdUser.sAMAccountName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $POWER_BI_STANDARD
$LicensesAdded += "POWER_BI_STANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($MEMBERS_CRMSTANDARD.SamAccountName -Contains $AdUser.sAMAccountName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $CRMSTANDARD
$LicensesAdded += "CRMSTANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($MEMBERS_INTUNE_A.SamAccountName -Contains $AdUser.sAMAccountName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $INTUNE_A
$LicensesAdded += "INTUNE_A"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($MEMBERS_OFFICESUBSCRIPTION_FACULTY.SamAccountName -Contains $AdUser.sAMAccountName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesAdded += "OFFICESUBSCRIPTION_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($MEMBERS_OFFICESUBSCRIPTION_STUDENT.SamAccountName -Contains $AdUser.sAMAccountName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesAdded += "OFFICESUBSCRIPTION_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
Catch [System.Exception]
{
Send-MailMessage -From admin@blah.com -To someadmin@blah.com -cc someotheradmin@blah.com -Subject "ERROR - O365 Licence Management" -Body $_.Exception.Message -SmtpServer smtp.blah.com
Write-Host $_.Exception.Message
}
$LoggingContent=$Date + ",User," + $User.UserPrincipalName + ",Licenses Added," + ($LicensesAdded -join ',')
# Write out the log
Add-Content $Logfile $LoggingContent
# If any errors occurred adding or removing icences - the variable $strMailBody will have some content, so send it to admins...
If ($strMailBody -ne $null)
{
Send-MailMessage -From admin@blah.com -To someadmin@blah.com -cc someotheradmin@blah.com -Subject "ERROR - O365 Licence Management" -Body $strMailBody -SmtpServer smtp.blah.com
Write-Host $strMailBody
}
}
}

Getting license details for your licensed O365 users

Part of the process of getting the script in the previous post working was having a record of who is licenced *now*.

This was done using the following script. Note that the commented lines must be un-commented to log the data, I am currently using this script to keep the AD groups up to date , hence the Add-ADGroupMember lines are uncommented. AD groups will soon be replacing the text files.

$ErrorActionPreference = "Continue"
$sig = @"
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct NativeCredential
{
public UInt32 Flags;
public CRED_TYPE Type;
public IntPtr TargetName;
public IntPtr Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public IntPtr CredentialBlob;
public UInt32 Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public IntPtr TargetAlias;
public IntPtr UserName;
internal static NativeCredential GetNativeCredential(Credential cred)
{
NativeCredential ncred = new NativeCredential();
ncred.AttributeCount = 0;
ncred.Attributes = IntPtr.Zero;
ncred.Comment = IntPtr.Zero;
ncred.TargetAlias = IntPtr.Zero;
ncred.Type = CRED_TYPE.GENERIC;
ncred.Persist = (UInt32)1;
ncred.CredentialBlobSize = (UInt32)cred.CredentialBlobSize;
ncred.TargetName = Marshal.StringToCoTaskMemUni(cred.TargetName);
ncred.CredentialBlob = Marshal.StringToCoTaskMemUni(cred.CredentialBlob);
ncred.UserName = Marshal.StringToCoTaskMemUni(System.Environment.UserName);
return ncred;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Credential
{
public UInt32 Flags;
public CRED_TYPE Type;
public string TargetName;
public string Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public string CredentialBlob;
public UInt32 Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public string TargetAlias;
public string UserName;
}
public enum CRED_TYPE : uint
{
GENERIC = 1,
DOMAIN_PASSWORD = 2,
DOMAIN_CERTIFICATE = 3,
DOMAIN_VISIBLE_PASSWORD = 4,
GENERIC_CERTIFICATE = 5,
DOMAIN_EXTENDED = 6,
MAXIMUM = 7, // Maximum supported cred type
MAXIMUM_EX = (MAXIMUM + 1000), // Allow new applications to run on old OSes
}
public class CriticalCredentialHandle : Microsoft.Win32.SafeHandles.CriticalHandleZeroOrMinusOneIsInvalid
{
public CriticalCredentialHandle(IntPtr preexistingHandle)
{
SetHandle(preexistingHandle);
}
public Credential GetCredential()
{
if (!IsInvalid)
{
NativeCredential ncred = (NativeCredential)Marshal.PtrToStructure(handle,
typeof(NativeCredential));
Credential cred = new Credential();
cred.CredentialBlobSize = ncred.CredentialBlobSize;
cred.CredentialBlob = Marshal.PtrToStringUni(ncred.CredentialBlob,
(int)ncred.CredentialBlobSize / 2);
cred.UserName = Marshal.PtrToStringUni(ncred.UserName);
cred.TargetName = Marshal.PtrToStringUni(ncred.TargetName`);
cred.TargetAlias = Marshal.PtrToStringUni(ncred.TargetAlias);
cred.Type = ncred.Type;
cred.Flags = ncred.Flags;
cred.Persist = ncred.Persist;
return cred;
}
else
{
throw new InvalidOperationException("Invalid CriticalHandle!");
}
}
override protected bool ReleaseHandle()
{
if (!IsInvalid)
{
CredFree(handle);
SetHandleAsInvalid();
return true;
}
return false;
}
}
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CredRead(string target, CRED_TYPE type, int reservedFlag, out IntPtr CredentialPtr);
[DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)]
public static extern bool CredFree([In] IntPtr cred);
"@
Add-Type -MemberDefinition $sig -Namespace "ADVAPI32" -Name 'Util'
$targetName = "LicenceManagment"
$nCredPtr= New-Object IntPtr
$success = [ADVAPI32.Util]::CredRead($targetName,1,0,[ref] $nCredPtr)
if($success){
$critCred = New-Object ADVAPI32.Util+CriticalCredentialHandle $nCredPtr
$cred = $critCred.GetCredential()
$UserName = $cred.UserName;
$Password = $cred.CredentialBlob;
$Password = ConvertTo-SecureString -String $Password -AsPlainText -Force
$objCreds = New-Object Management.Automation.PSCredential $UserName, $Password
}
####
If(@(Get-Module | ? { $_.Name -eq "MSOnline"}).Count -eq 0)
{
Import-Module MSOnline;
}
If(@(Get-Module | ? { $_.Name -eq "ActiveDirectory"}).Count -eq 0)
{
Import-Module ActiveDirectory;
}
$LoggingFile="C:\Office365-Scripts\LicenceLog.txt"
$POWER_BI_STANDARD="C:\Office365-Scripts\POWER_BI_STANDARD.txt"
$STANDARDWOFFPACK_FACULTY="C:\Office365-Scripts\STANDARDWOFFPACK_FACULTY.txt"
$OFFICESUBSCRIPTION_FACULTY="C:\Office365-Scripts\OFFICESUBSCRIPTION_FACULTY.txt"
$OFFICESUBSCRIPTION_STUDENT="C:\Office365-Scripts\OFFICESUBSCRIPTION_STUDENT.txt"
$STANDARDWOFFPACK_IW_STUDENT="C:\Office365-Scripts\STANDARDWOFFPACK_IW_STUDENT.txt"
$CRMSTANDARD="C:\Office365-Scripts\CRMSTANDARD.txt"
$INTUNE_A="C:\Office365-Scripts\INTUNE_A.txt"
$STANDARDWOFFPACK_IW_FACULTY="C:\Office365-Scripts\STANDARDWOFFPACK_IW_FACULTY.txt"
$PROJECTONLINE_PLAN_1_FACULTY="C:\Office365-Scripts\PROJECTONLINE_PLAN_1_FACULTY.txt"
$STANDARDWOFFPACK_STUDENT="C:\Office365-Scripts\STANDARDWOFFPACK_STUDENT.txt"
Connect-MsolService -Credential $objCreds
$Users=Get-MsolUser -all | where {$_.isLicensed -eq "True"}
ForEach ($User in $Users)
{
If($User.UserPrincipalName -notlike "*<YourTenancyName>.onmicrosoft.com" -and $User.UserPrincipalName -ne "DirSync@blah.com")
{
$AdUser=Get-ADUser -Filter {UserPrincipalName -eq $User.UserPrincipalName} -Properties extensionAttribute5, sAMAccountName
$List=$NULL
$Licences=$User.Licenses
$SKUIDs=$Licences.AccountSkuId
ForEach ($SKU in $SKUIDs)
{
If ($SKU -eq "<YourTenancyName>:POWER_BI_STANDARD")
{
Add-ADGroupMember -Identity POWER_BI_STANDARD_Users -Members $AdUser.sAMAccountName
#Add-Content $POWER_BI_STANDARD $User.UserPrincipalName
}
If ($SKU -eq "<YourTenancyName>:STANDARDWOFFPACK_FACULTY")
{
Add-ADGroupMember -Identity STANDARDWOFFPACK_FACULTY_Users -Members $AdUser.sAMAccountName
#Add-Content $STANDARDWOFFPACK_FACULTY $User.UserPrincipalName
}
If ($SKU -eq "<YourTenancyName>:OFFICESUBSCRIPTION_FACULTY")
{
Add-ADGroupMember -Identity OFFICESUBSCRIPTION_FACULTY_Users -Members $AdUser.sAMAccountName
#Add-Content $OFFICESUBSCRIPTION_FACULTY $User.UserPrincipalName
}
If ($SKU -eq "<YourTenancyName>:OFFICESUBSCRIPTION_STUDENT")
{
Add-ADGroupMember -Identity OFFICESUBSCRIPTION_STUDENT_Users -Members $AdUser.sAMAccountName
#Add-Content $OFFICESUBSCRIPTION_STUDENT $User.UserPrincipalName
}
#If ($SKU -eq "<YourTenancyName>:STANDARDWOFFPACK_IW_STUDENT")
#{
##Add-Content $STANDARDWOFFPACK_IW_STUDENT $User.UserPrincipalName
#}
If ($SKU -eq "<YourTenancyName>:CRMSTANDARD")
{
Add-ADGroupMember -Identity CRMSTANDARD_Users -Members $AdUser.sAMAccountName
#Add-Content $CRMSTANDARD $User.UserPrincipalName
}
If ($SKU -eq "<YourTenancyName>:INTUNE_A")
{
Add-ADGroupMember -Identity INTUNE_A_Users -Members $AdUser.sAMAccountName
#Add-Content $INTUNE_A $User.UserPrincipalName
}
#If ($SKU -eq "<YourTenancyName>:STANDARDWOFFPACK_IW_FACULTY")
#{
##Add-Content $STANDARDWOFFPACK_IW_FACULTY $User.UserPrincipalName
#}
If ($SKU -eq "<YourTenancyName>:PROJECTONLINE_PLAN_1_FACULTY")
{
Add-ADGroupMember -Identity PROJECTONLINE_PLAN_1_FACULTY_Users -Members $AdUser.sAMAccountName
#Add-Content $PROJECTONLINE_PLAN_1_FACULTY $User.UserPrincipalName
}
If ($SKU -eq "<YourTenancyName>:STANDARDWOFFPACK_STUDENT")
{
Add-ADGroupMember -Identity STANDARDWOFFPACK_STUDENT_Users -Members $AdUser.sAMAccountName
#Add-Content $STANDARDWOFFPACK_STUDENT $User.UserPrincipalName
}
$List = $List + $SKU + "|"
}
Sort-object $List
Write-Host $List
$Content=$User.UserPrincipalName + "|" + $List
#Add-Content $LoggingFile $Content
}
}

Office 365 Licence Management

Since introducing O365 to my organisation, there has been a steady flow of people wanting to use services within it. The licences for which have been applied on an ad-hoc basis by several global admins.

Now we are in a position to make these services more official/ production, I needed to licence those users who were not yet licensed, plus sort out the improperly licensed people.

It seems that either one of those global admins who was assigning licences or maybe self registered users were getting the Information Worker licences – e.g. STANDARDWOFFPACK_IW_STUDENT. This was not desired, so my script had to sort those out as well!

Additionally, people whose status changed from being staff to anything else needed to have any staff licence revoked and replaced with a student licence – and vice versa.

I also wanted to control who should be given those individual licences, like Office Pro Plus and Dynamics. For the moment, those entitled to these licensed are held in text files – I’m working on migrating to using AD groups instead, but for now just needed something that just works!

The script logs added and removed licences, to C:\Office365-Scripts\Licencing\LicenceManagement.txt

Error emails are based on the content of the $error variable, using a function to generate the mail body.

Here is the script:

$ErrorActionPreference = "Stop"
$Error.Clear()
#####################################################
# Function to generate mail content for licencing errors
Function MailBody
{
$Exception=$error[0].Exception.Message
$Command=$error[0].InvocationInfo.Line
$StrBody="$Exception `r`r$Command `r`r##########################################################################################`r`r"
$Error.Clear()
Return $strBody
}
#####################################################
$sig = @"
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct NativeCredential
{
public UInt32 Flags;
public CRED_TYPE Type;
public IntPtr TargetName;
public IntPtr Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public IntPtr CredentialBlob;
public UInt32 Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public IntPtr TargetAlias;
public IntPtr UserName;
internal static NativeCredential GetNativeCredential(Credential cred)
{
NativeCredential ncred = new NativeCredential();
ncred.AttributeCount = 0;
ncred.Attributes = IntPtr.Zero;
ncred.Comment = IntPtr.Zero;
ncred.TargetAlias = IntPtr.Zero;
ncred.Type = CRED_TYPE.GENERIC;
ncred.Persist = (UInt32)1;
ncred.CredentialBlobSize = (UInt32)cred.CredentialBlobSize;
ncred.TargetName = Marshal.StringToCoTaskMemUni(cred.TargetName);
ncred.CredentialBlob = Marshal.StringToCoTaskMemUni(cred.CredentialBlob);
ncred.UserName = Marshal.StringToCoTaskMemUni(System.Environment.UserName);
return ncred;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Credential
{
public UInt32 Flags;
public CRED_TYPE Type;
public string TargetName;
public string Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public string CredentialBlob;
public UInt32 Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public string TargetAlias;
public string UserName;
}
public enum CRED_TYPE : uint
{
GENERIC = 1,
DOMAIN_PASSWORD = 2,
DOMAIN_CERTIFICATE = 3,
DOMAIN_VISIBLE_PASSWORD = 4,
GENERIC_CERTIFICATE = 5,
DOMAIN_EXTENDED = 6,
MAXIMUM = 7, // Maximum supported cred type
MAXIMUM_EX = (MAXIMUM + 1000), // Allow new applications to run on old OSes
}
public class CriticalCredentialHandle : Microsoft.Win32.SafeHandles.CriticalHandleZeroOrMinusOneIsInvalid
{
public CriticalCredentialHandle(IntPtr preexistingHandle)
{
SetHandle(preexistingHandle);
}
public Credential GetCredential()
{
if (!IsInvalid)
{
NativeCredential ncred = (NativeCredential)Marshal.PtrToStructure(handle,
typeof(NativeCredential));
Credential cred = new Credential();
cred.CredentialBlobSize = ncred.CredentialBlobSize;
cred.CredentialBlob = Marshal.PtrToStringUni(ncred.CredentialBlob,
(int)ncred.CredentialBlobSize / 2);
cred.UserName = Marshal.PtrToStringUni(ncred.UserName);
cred.TargetName = Marshal.PtrToStringUni(ncred.TargetName`);
cred.TargetAlias = Marshal.PtrToStringUni(ncred.TargetAlias);
cred.Type = ncred.Type;
cred.Flags = ncred.Flags;
cred.Persist = ncred.Persist;
return cred;
}
else
{
throw new InvalidOperationException("Invalid CriticalHandle!");
}
}
override protected bool ReleaseHandle()
{
if (!IsInvalid)
{
CredFree(handle);
SetHandleAsInvalid();
return true;
}
return false;
}
}
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CredRead(string target, CRED_TYPE type, int reservedFlag, out IntPtr CredentialPtr);
[DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)]
public static extern bool CredFree([In] IntPtr cred);
"@
Add-Type -MemberDefinition $sig -Namespace "ADVAPI32" -Name 'Util'
$targetName = "LicenceManagment"
$nCredPtr= New-Object IntPtr
$success = [ADVAPI32.Util]::CredRead($targetName,1,0,[ref] $nCredPtr)
if($success){
$critCred = New-Object ADVAPI32.Util+CriticalCredentialHandle $nCredPtr
$cred = $critCred.GetCredential()
$UserName = $cred.UserName;
$Password = $cred.CredentialBlob;
$Password = ConvertTo-SecureString -String $Password -AsPlainText -Force
$objCreds = New-Object Management.Automation.PSCredential $UserName, $Password
}
############ Import modules and login to MSOL ############
If(@(Get-Module | ? { $_.Name -eq "MSOnline"}).Count -eq 0)
{
Import-Module MSOnline;
}
If(@(Get-Module | ? { $_.Name -eq "ActiveDirectory"}).Count -eq 0)
{
Import-Module ActiveDirectory;
}
Try
{
Connect-MsolService -Credential $objCreds
}
Catch [System.Exception]
{
Send-MailMessage -From myadmin@blah.com -To someone@blah.com -cc someone-else@blah.com -Subject "ERROR - License management Login Failed!" -Body $_.Exception.Message -SmtpServer mysmtpserver.blah.com
Exit
}
############ Setup Variables ############
$dateFormat = "HH:mm:ss dd/MM/yyyy"
############ Setup logging file ############
$Logfile="C:\Office365-Scripts\Licencing\LicenceManagement.txt"
############ Files fontaining the UPN's of user who should have individual Licenses ############
$CRMSTANDARD_Users="C:\Office365-Scripts\Licencing\Input\CRMSTANDARD.txt"
[System.Collections.ArrayList]$Array_CRMSTANDARD=Get-Content $CRMSTANDARD_Users
$INTUNE_A_Users="C:\Office365-Scripts\Licencing\Input\INTUNE_A.txt"
[System.Collections.ArrayList]$Array_INTUNE_A=Get-Content $INTUNE_A_Users
$OFFICESUBSCRIPTION_FACULTY_Users="C:\Office365-Scripts\Licencing\Input\OFFICESUBSCRIPTION_FACULTY.txt"
[System.Collections.ArrayList]$Array_OFFICESUBSCRIPTION_FACULTY=Get-Content $OFFICESUBSCRIPTION_FACULTY_Users
$OFFICESUBSCRIPTION_STUDENT_Users="C:\Office365-Scripts\Licencing\Input\OFFICESUBSCRIPTION_STUDENT.txt"
[System.Collections.ArrayList]$Array_OFFICESUBSCRIPTION_STUDENT=Get-Content $OFFICESUBSCRIPTION_STUDENT_Users
$POWER_BI_STANDARD_Users="C:\Office365-Scripts\Licencing\Input\POWER_BI_STANDARD.txt"
[System.Collections.ArrayList]$Array_POWER_BI_STANDARD=Get-Content $POWER_BI_STANDARD_Users
$PROJECTONLINE_PLAN_1_FACULTY_Users="C:\Office365-Scripts\Licencing\Input\PROJECTONLINE_PLAN_1_FACULTY.txt"
[System.Collections.ArrayList]$Array_PROJECTONLINE_PLAN_1_FACULTY=Get-Content $PROJECTONLINE_PLAN_1_FACULTY_Users
$PROJECTONLINE_PLAN_1_STUDENT_Users="C:\Office365-Scripts\Licencing\Input\PROJECTONLINE_PLAN_1_STUDENT.txt"
[System.Collections.ArrayList]$Array_PROJECTONLINE_PLAN_1_STUDENT=Get-Content $PROJECTONLINE_PLAN_1_STUDENT_Users
############ Standard Licencing ############
$POWER_BI_STANDARD = "<YourTenancyName>:POWER_BI_STANDARD"
$CRMSTANDARD = "<YourTenancyName>:CRMSTANDARD"
$INTUNE_A = "<YourTenancyName>:INTUNE_A"
############ Faculty Licensing ############
$STANDARDWOFFPACK_FACULTY = "<YourTenancyName>:STANDARDWOFFPACK_FACULTY"
$OFFICESUBSCRIPTION_FACULTY = "<YourTenancyName>:OFFICESUBSCRIPTION_FACULTY"
$STANDARDWOFFPACK_IW_FACULTY = "<YourTenancyName>:STANDARDWOFFPACK_IW_FACULTY"
$PROJECTONLINE_PLAN_1_FACULTY ="<YourTenancyName>:PROJECTONLINE_PLAN_1_FACULTY"
############ Student Licensing ############
$STANDARDWOFFPACK_STUDENT = "<YourTenancyName>:STANDARDWOFFPACK_STUDENT"
$STANDARDWOFFPACK_IW_STUDENT = "<YourTenancyName>:STANDARDWOFFPACK_IW_STUDENT"
$PROJECTONLINE_PLAN_1_STUDENT = "<YourTenancyName>:PROJECTONLINE_PLAN_1_STUDENT"
$OFFICESUBSCRIPTION_STUDENT = "<YourTenancyName>:OFFICESUBSCRIPTION_STUDENT"
############Generic settings ############
$DisabledPlans = "EXCHANGE_S_STANDARD"
$UsageLocation = "GB"
############ Define the two types of Licence option - Faculty and Student ############
$FacultyLicenseOptions = New-MsolLicenseOptions -AccountSkuId $STANDARDWOFFPACK_FACULTY -DisabledPlans $DisabledPlans
$StudentLicenseOptions = New-MsolLicenseOptions -AccountSkuId $STANDARDWOFFPACK_STUDENT -DisabledPlans $DisabledPlans
#
############ Get users and apply Licenses ############
#
############ Do the licenced users first ############
ForEach($User in (Get-MsolUser -all | where {$_.isLicensed -eq "True"}))
{
If($User.UserPrincipalName -notlike "*<YourTenancyName>.onmicrosoft.com" -and $User.UserPrincipalName -ne "DirSync@blah.com")
{
$AdUser=Get-ADUser -Filter {UserPrincipalName -eq $User.UserPrincipalName} -Properties extensionAttribute5
Try
{
$date = Get-Date -Format $dateFormat
$LoggingContent=$null
$Licenses=$null
$SKUIDs=$null
$STANDARDWOFFPACK_STUDENT_Applied=$null
$STANDARDWOFFPACK_FACULTY_Applied=$null
$PROJECTONLINE_PLAN_1_FACULTY_Applied=$null
$POWER_BI_STANDARD_Applied=$null
$CRMSTANDARD_Applied=$null
$INTUNE_A_Applied=$null
$OFFICESUBSCRIPTION_FACULTY_Applied=$null
$LicensesAdded=@()
$LicensesRemoved=@()
$Licenses=$User.Licenses
$SKUIDs=$Licenses.AccountSkuId
ForEach ($SKU in $SKUIDs)
{
If ($SKU -eq $STANDARDWOFFPACK_IW_FACULTY)
{
Try
{
##### These should not be used, so remove if found #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_IW_FACULTY
$LicensesRemoved += "STANDARDWOFFPACK_IW_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
##### But then we need to replace that with a "normal" O365 licence, plus Pro Plus #####
If ($AdUser.extensionAttribute5 -eq "Staff")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_FACULTY -LicenseOptions $FacultyLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesAdded += "OFFICESUBSCRIPTION_FACULTY"
##### Add content to the licencing file to ensure that they licence is not subsequently removed.... #####
Add-Content $OFFICESUBSCRIPTION_FACULTY_Users $User.UserPrincipalName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
Else
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_STUDENT -LicenseOptions $FacultyLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesAdded += "OFFICESUBSCRIPTION_STUDENT"
##### Add content to the licencing file to ensure that they licence is not subsequently removed.... #####
Add-Content $OFFICESUBSCRIPTION_FACULTY_Users $User.UserPrincipalName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $STANDARDWOFFPACK_IW_STUDENT)
{
Try
{
##### These should not be used, so remove if found #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_IW_STUDENT
$LicensesRemoved += "STANDARDWOFFPACK_IW_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
##### But then we need to replace that with a "normal" O365 licence, plus Pro Plus #####
If ($AdUser.extensionAttribute5 -ne "Staff")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_STUDENT -LicenseOptions $FacultyLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesAdded += "OFFICESUBSCRIPTION_STUDENT"
##### Add content to the licencing file to ensure that they licence is not subsequently removed.... #####
Add-Content $OFFICESUBSCRIPTION_FACULTY_Users $User.UserPrincipalName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
Else
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_FACULTY -LicenseOptions $FacultyLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesAdded += "OFFICESUBSCRIPTION_FACULTY"
##### Add content to the licencing file to ensure that they licence is not subsequently removed.... #####
Add-Content $OFFICESUBSCRIPTION_FACULTY_Users $User.UserPrincipalName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
##### Standard O365 Licenses #####
If ($SKU -eq $STANDARDWOFFPACK_STUDENT)
{
$STANDARDWOFFPACK_STUDENT_Applied="True"
If ($ADUser.extensionAttribute5 -eq "Staff")
{
Try
{
##### Remove Student licence from Staff member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_STUDENT
$LicensesRemoved += "STANDARDWOFFPACK_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Staff licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_FACULTY -LicenseOptions $FacultyLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $STANDARDWOFFPACK_FACULTY)
{
$STANDARDWOFFPACK_FACULTY_Applied="True"
If ($ADUser.extensionAttribute5 -ne "Staff")
{
Try
{
##### Remove Staff licence from Student member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $STANDARDWOFFPACK_FACULTY
$LicensesRemoved += "STANDARDWOFFPACK_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Student licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_STUDENT -LicenseOptions $StudentLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
##### Individual Subscriptions #####
If ($SKU -eq $PROJECTONLINE_PLAN_1_FACULTY)
{
$PROJECTONLINE_PLAN_1_FACULTY_Applied="True"
If ($Array_PROJECTONLINE_PLAN_1_FACULTY -NotContains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesRemoved += "PROJECTONLINE_PLAN_1_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
ElseIf ($ADUser.extensionAttribute5 -ne "Staff")
{
Try
{
##### Remove Staff licence from Student member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesRemoved += "PROJECTONLINE_PLAN_1_FACULTY"
##### Remove the entry relating to this user from the licencing file to ensure that the licence is not subsequently/ mistakenly added again.... #####
$Array_PROJECTONLINE_PLAN_1_FACULTY.Remove($User.UserPrincipalName)
Clear-Content $PROJECTONLINE_PLAN_1_STUDENT_Users
ForEach ($UserObject in $Array_PROJECTONLINE_PLAN_1_FACULTY)
{
Add-Content $PROJECTONLINE_PLAN_1_FACULTY_Users $UserObject
}
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Student licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_STUDENT
$LicensesAdded += "PROJECTONLINE_PLAN_1_STUDENT"
##### Add content to the licencing file to ensure that the licence is not subsequently removed.... #####
Add-Content $PROJECTONLINE_PLAN_1_STUDENT_Users $User.UserPrincipalName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $PROJECTONLINE_PLAN_1_STUDENT)
{
$PROJECTONLINE_PLAN_1_STUDENT_Applied="True"
If ($Array_PROJECTONLINE_PLAN_1_STUDENT -NotContains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $PROJECTONLINE_PLAN_1_STUDENT
$LicensesRemoved += "PROJECTONLINE_PLAN_1_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
ElseIf ($ADUser.extensionAttribute5 -eq "Staff")
{
Try
{
##### Remove Student licence from Staff member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $PROJECTONLINE_PLAN_1_STUDENT
$LicensesRemoved += "PROJECTONLINE_PLAN_1_STUDENT"
##### Remove the entry relating to this user from the licencing file to ensure that the licence is not subsequently/ mistakenly added again.... #####
$Array_PROJECTONLINE_PLAN_1_STUDENT.Remove($User.UserPrincipalName)
Clear-Content $PROJECTONLINE_PLAN_1_STUDENT_Users
ForEach ($UserObject in $Array_PROJECTONLINE_PLAN_1_STUDENT)
{
Add-Content $PROJECTONLINE_PLAN_1_STUDENT_Users $UserObject
}
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Staff licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesAdded += "PROJECTONLINE_PLAN_1_FACULTY"
##### Add content to the licencing file to ensure that the licence is not subsequently removed.... #####
Add-Content $PROJECTONLINE_PLAN_1_FACULTY_Users $User.UserPrincipalName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $OFFICESUBSCRIPTION_FACULTY)
{
$OFFICESUBSCRIPTION_FACULTY_Applied="True"
If ($Array_OFFICESUBSCRIPTION_FACULTY -NotContains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesRemoved += "OFFICESUBSCRIPTION_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
ElseIf ($ADUser.extensionAttribute5 -ne "Staff")
{
Try
{
##### Remove Staff licence from Student member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesRemoved += "OFFICESUBSCRIPTION_FACULTY"
##### Remove the entry relating to this user from the licencing file to ensure that the licence is not subsequently/ mistakenly added again.... #####
$Array_OFFICESUBSCRIPTION_FACULTY.Remove($User.UserPrincipalName)
Clear-Content $OFFICESUBSCRIPTION_FACULTY_Users
ForEach ($UserObject in $Array_OFFICESUBSCRIPTION_FACULTY)
{
Add-Content $OFFICESUBSCRIPTION_FACULTY_Users $UserObject
}
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Student licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesAdded += "OFFICESUBSCRIPTION_STUDENT"
##### Add content to the licencing file to ensure that the licence is not subsequently removed.... #####
Add-Content $OFFICESUBSCRIPTION_STUDENT_Users $User.UserPrincipalName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $OFFICESUBSCRIPTION_STUDENT)
{
$OFFICESUBSCRIPTION_STUDENT_Applied="True"
If ($Array_OFFICESUBSCRIPTION_STUDENT -NotContains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesRemoved += "OFFICESUBSCRIPTION_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
ElseIf ($ADUser.extensionAttribute5 -eq "Staff")
{
Try
{
##### Remove Student licence from Staff member #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $OFFICESUBSCRIPTION_STUDENT
$LicensesRemoved += "OFFICESUBSCRIPTION_STUDENT"
##### Remove the entry relating to this user from the licencing file to ensure that the licence is not subsequently/ mistakenly added again.... #####
$Array_OFFICESUBSCRIPTION_STUDENT.Remove($User.UserPrincipalName)
Clear-Content $OFFICESUBSCRIPTION_STUDENT_Users
ForEach ($UserObject in $Array_OFFICESUBSCRIPTION_STUDENT)
{
Add-Content $OFFICESUBSCRIPTION_STUDENT_Users $UserObject
}
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
Try
{
##### Apply Staff licence #####
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesAdded += "OFFICESUBSCRIPTION_FACULTY"
##### Add content to the licencing file to ensure that the licence is not subsequently removed.... #####
Add-Content $OFFICESUBSCRIPTION_FACULTY_Users $User.UserPrincipalName
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $POWER_BI_STANDARD)
{
$POWER_BI_STANDARD_Applied="True"
If ($Array_POWER_BI_STANDARD -NotContains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $POWER_BI_STANDARD
$LicensesRemoved += "POWER_BI_STANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $CRMSTANDARD)
{
$CRMSTANDARD_Applied="True"
If ($Array_CRMSTANDARD -NotContains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $CRMSTANDARD
$LicensesRemoved += "CRMSTANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
If ($SKU -eq $INTUNE_A)
{
$INTUNE_A_Applied="True"
If ($Array_INTUNE_A -NotContains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $INTUNE_A
$LicensesRemoved += "INTUNE_A"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
}
}
Catch [System.Exception]
{
#Mop up any other errors
Send-MailMessage -From myadmin@blah.com -To someone@blah.com -cc someone-else@blah.com -Subject "ERROR - O365 Licence Management" -Body $_.Exception.Message -SmtpServer mysmtpserver.blah.com
}
Try
{
##### Apply individual licences if they are not applied already #####
If ($Array_PROJECTONLINE_PLAN_1_FACULTY -Contains $User.UserPrincipalName -and $PROJECTONLINE_PLAN_1_FACULTY_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesAdded += "PROJECTONLINE_PLAN_1_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($Array_PROJECTONLINE_PLAN_1_STUDENT -Contains $User.UserPrincipalName -and $PROJECTONLINE_PLAN_1_STUDENT_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_STUDENT
$LicensesAdded += "PROJECTONLINE_PLAN_1_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($Array_POWER_BI_STANDARD -Contains $User.UserPrincipalName -and $POWER_BI_STANDARD_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $POWER_BI_STANDARD
$LicensesAdded += "POWER_BI_STANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($Array_CRMSTANDARD -Contains $User.UserPrincipalName -and $CRMSTANDARD_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $CRMSTANDARD
$LicensesAdded += "CRMSTANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($Array_INTUNE_A -Contains $User.UserPrincipalName -and $INTUNE_A_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $INTUNE_A
$LicensesAdded += "INTUNE_A"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($Array_OFFICESUBSCRIPTION_FACULTY -Contains $User.UserPrincipalName -and $OFFICESUBSCRIPTION_FACULTY_Applied -ne "True")
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesAdded += "OFFICESUBSCRIPTION_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
Catch [System.Exception]
{
#Mop up any other errors
Send-MailMessage -From myadmin@blah.com -To someone@blah.com -cc someone-else@blah.com -Subject "ERROR - O365 Licence Management" -Body $_.Exception.Message -SmtpServer mysmtpserver.blah.com
}
#Reporting bits:
If ($LicensesAdded.Count -eq 0 -and $LicensesRemoved.Count -gt 0)
{
$LoggingContent=$Date + ",User," + $User.UserPrincipalName + ",LicensesRemoved," + ($LicensesRemoved -join ',')
}
If ($LicensesAdded.Count -gt 0 -and $LicensesRemoved.Count -eq 0)
{
$LoggingContent=$Date + ",User," + $User.UserPrincipalName + ",Licenses Added," + ($LicensesAdded -join ',')
}
If ($LicensesAdded.Count -gt 0 -and $LicensesRemoved.Count -gt 0)
{
$LoggingContent=$Date + ",User," + $User.UserPrincipalName + ",Licenses Added," + ($LicensesAdded -join ',') + ",LicensesRemoved," + ($LicensesRemoved -join ',')
}
# Write out the log
Add-Content $Logfile $LoggingContent
# If any errors occurred adding or removing icences - the variable $strMailBody will have some content, so send it to someone who cares...
If ($strMailBody -ne $null)
{
Send-MailMessage -From myadmin@blah.com -To someone@blah.com -cc someone-else@blah.com -Subject "ERROR - O365 Licence Management" -Body $strMailBody -SmtpServer mysmtpserver.blah.com
}
}
}
############ Now mop up the unlicenced users ############
ForEach($User in (Get-MsolUser -all | where{$_.isLicensed -ne "True"}))
{
If($User.UserPrincipalName -notlike "*<YourTenancyName>.onmicrosoft.com" -and $User.UserPrincipalName -ne "DirSync@blah.com")
{
$date = Get-Date -Format $dateFormat
$LoggingContent=$null
$LicensesAdded=@()
$AdUser=Get-ADUser -Filter {UserPrincipalName -eq $User.UserPrincipalName} -Properties extensionAttribute5
Try
{
If ($ADUser.extensionAttribute5 -eq "Staff")
{
Try
{
# Set usage location
Set-MsolUser -UserPrincipalName $User.UserPrincipalName -UsageLocation $UsageLocation
}
Catch [System.Exception]
{
$strBody="Error setting UsageLocation for $User.UserPrincipalName"
$strMailBody=$strMailBody+$strBody
}
Try
{
# Set standard O365 licence without Exchange
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_FACULTY -LicenseOptions $FacultyLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($ADUser.extensionAttribute5 -ne "Staff")
{
Try
{
# Set usage location
Set-MsolUser -UserPrincipalName $User.UserPrincipalName -UsageLocation $UsageLocation
}
Catch [System.Exception]
{
$strBody="Error setting UsageLocation for $User.UserPrincipalName"
$strMailBody=$strMailBody+$strBody
}
Try
{
# Set standard O365 licence without Exchange
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $STANDARDWOFFPACK_STUDENT -LicenseOptions $StudentLicenseOptions
$LicensesAdded += "STANDARDWOFFPACK_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
##### Individual Subscriptions #####
If ($Array_PROJECTONLINE_PLAN_1_FACULTY -Contains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_FACULTY
$LicensesAdded += "PROJECTONLINE_PLAN_1_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($Array_PROJECTONLINE_PLAN_1_STUDENT -Contains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $PROJECTONLINE_PLAN_1_STUDENT
$LicensesAdded += "PROJECTONLINE_PLAN_1_STUDENT"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($Array_POWER_BI_STANDARD -Contains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $POWER_BI_STANDARD
$LicensesAdded += "POWER_BI_STANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($Array_CRMSTANDARD -Contains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $CRMSTANDARD
$LicensesAdded += "CRMSTANDARD"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($Array_INTUNE_A -Contains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $INTUNE_A
$LicensesAdded += "INTUNE_A"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
If ($Array_OFFICESUBSCRIPTION_FACULTY -Contains $User.UserPrincipalName)
{
Try
{
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $OFFICESUBSCRIPTION_FACULTY
$LicensesAdded += "OFFICESUBSCRIPTION_FACULTY"
}
Catch [System.Exception]
{
$strBody=MailBody
$strMailBody=$strMailBody+$strBody
}
}
}
Catch [System.Exception]
{
Send-MailMessage -From myadmin@blah.com -To someone@blah.com -cc someone-else@blah.com -Subject "ERROR - O365 Licence Management" -Body $_.Exception.Message -SmtpServer mysmtpserver.blah.com
}
$LoggingContent=$Date + ",User," + $User.UserPrincipalName + ",Licenses Added," + ($LicensesAdded -join ',')
# Write out the log
Add-Content $Logfile $LoggingContent
# If any errors occurred adding or removing icences - the variable $strMailBody will have some content, so send it to someone who cares...
If ($strMailBody -ne $null)
{
Send-MailMessage -From myadmin@blah.com -To someone@blah.com -cc someone-else@blah.com -Subject "ERROR - O365 Licence Management" -Body $strMailBody -SmtpServer mysmtpserver.blah.com
}
}
}