I have a project to assign licenses to users within O365. I’m fine with the process of adding, removing, configuring etc. but would like to make this a little tidier.
Basically I have the below code which configures an already enabled licence (ENTERPRISEPACK) and enables another (EMS):
$TargetUsers = Get-ADUser -Filter * -SearchBase "OU=To Migrate,OU=Department,OU=Company,DC=Domain,DC=local"
$O365EntE3 = New-MsolLicenseOptions -AccountSkuId tenent:ENTERPRISEPACK #-DisabledPlans MCOSTANDARD
$EMSE3 = New-MsolLicenseOptions -AccountSkuId tenent:EMS
#Loop through the found users and set required licenses.
$TargetUsers | ForEach-Object {
Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -LicenseOptions $O365EntE3
Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -AddLicenses callcreditgroup:EMS
}
This works fine but where an EMS licence is already assigned, it will error on subsequent runs with the following error:
Set-MsolUserLicense : Unable to assign this license because it is invalid. Use the Get-MsolAccountSku cmdlet to retrieve a list of valid licenses.
Yes that would be a good solution. Not something I’ve really used in my scripts before so will have a little read up but suppose I was hoping that I could address this with a “where” cmdlet or “If” conditional logic etc.
#Currently setting all services within this plan
$O365EntE3 = New-MsolLicenseOptions -AccountSkuId tenent:ENTERPRISEPACK #-DisabledPlans MCOSTANDARD
#Currently setting all services within this plan
$EMSE3 = New-MsolLicenseOptions -AccountSkuId tenent:EMS
#Loop through the found users and set required licenses.
$TargetUsers | ForEach-Object {
Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -LicenseOptions $O365EntE3
Try
{
Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -AddLicenses tenent:EMS -ErrorAction Stop
}
Catch
{
Write-Warning "EMS Licence already assigned"
}
}
But would like the output message to include each username that that may already have this. Adding $TargetUsers to the message just lists all users in one line regardless of whether they already have the license or not.
I did already try along those lines but $_ in this instance returns the error “Unable to assign this license because it is invalid. Use the Get-MsolAccountSku cmdlet to retrieve a list of valid licenses.” rather than user it’s working with
I did try another route:
#Currently setting all services within this plan
$O365EntE3 = New-MsolLicenseOptions -AccountSkuId tenent:ENTERPRISEPACK #-DisabledPlans MCOSTANDARD
#Currently setting all services within this plan
$EMSE3 = New-MsolLicenseOptions -AccountSkuId tenent:EMS
#Loop through the found users and set required licenses.
ForEach ($TargetUser in $TargetUsers) {
Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -LicenseOptions $O365EntE3
Try
{
Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -AddLicenses tenent:EMS -ErrorAction Stop
}
Catch
{
Write-Warning "EMS Licence already assigned to $TargetUser"
}
}
but this just fails all commands and returns:
Set-MsolUserLicense : Cannot bind argument to parameter 'UserPrincipalName' because it is null.
At line:50 char:44
+ ... Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -Licens ...
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Set-MsolUserLicense], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.Online.Administration.Automation.SetUserLicense
You need to write the property “$TargetUser.PrimarySmtpAddress”
Only use “$_.Property” when using the Foreach-Object loop.
On the “foreach ($TargetUser in $TargetUsers)” loop, you need to use “$TargetUser.Property”