Assign O365 product licence only where not already assigned

This topic contains 8 replies, has 3 voices, and was last updated by  Vandrey Trindade 3 months, 3 weeks ago.

  • Author
    Posts
  • #74116

    Jamie
    Participant

    Hi,

    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.

    The following Technet article mentions this in the security note just past half way down the page but not how to address it: https://technet.microsoft.com/en-us/library/dn771770.aspx

    Is there a way to run this command only the product unlicensed?

    My thinking is along the lines of:

    Where-Object {$_.IsLicensed -eq "false"} | set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -AddLicenses callcreditgroup:EMS

    but this isn't specifying the product before the pipe so obviously won't work. Any way to do this or am I doomed to just accept the error?

    Cheers
    Jamie

  • #74201

    Don Jones
    Keymaster

    If it's an error you can anticipate and deal with, or ignore, why not just handle the error? As in, a Try/Catch?

  • #74224

    Jamie
    Participant

    Hi Don,

    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.

    Thanks for the advice.

    Jamie

  • #74231

    Jamie
    Participant

    OK, so the following works nicely:

    #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.

    Cheers
    Jamie

  • #74243

    Vandrey Trindade
    Participant

    Jamie,

    Try to add the $_.DisplayName (or the property that you want) instead of $TargetUsers on the warning message.

  • #74270

    Jamie
    Participant

    Hi Vandrey,

    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

    Cheers
    Jamie

  • #74273

    Vandrey Trindade
    Participant

    Jamie,

    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"

    Try this:

    ForEach ($TargetUser in $TargetUsers) { 
        Set-MsolUserLicense -UserPrincipalName $TargetUser.PrimarySmtpAddress -LicenseOptions $O365EntE3
            Try
            {
                Set-MsolUserLicense -UserPrincipalName $TargetUser.PrimarySmtpAddress -AddLicenses tenent:EMS -ErrorAction Stop
            }
            Catch
            {
                Write-Warning "EMS Licence already assigned to TargetUser.PrimarySmtpAddress"
            }
        }
  • #74275

    Jamie
    Participant

    You beat me to it.....I've been having a play around and the figured out the following works which is pretty much exactly what you said!:

    foreach ($User in $TargetUsers) {
        Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -LicenseOptions $O365EntE3
        Write-Information -MessageData "All Office 365 Enterprise E3 services enabled for $($User.UserPrincipalName)" -InformationAction Continue
            Try
            {
                Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses tenent:EMS -ErrorAction Stop            
                Write-Information -MessageData "EMS Product enabled for $($SUser.UserPrincipalName)" -InformationAction Continue
            }
            Catch
            {
                Write-Warning "EMS Licence already assigned to $($User.UserPrincipalName)"
            }
        }

    Noted of when to use the $_.Property. Thanks for the advice.

  • #74279

    Vandrey Trindade
    Participant

    Great! Glad that it worked! 😀

You must be logged in to reply to this topic.