Cmdlet/Convert-MSOLUserLIcenseToExplict.ps1
# Converts from an inherited SKU to an Explicit SKU with the same plan settings Function Convert-MSOLUserLicenseToExplicit { <# .SYNOPSIS Converts a specified SKU from Group assiged to Explicitly assigned .DESCRIPTION Will explicitly apply the SKU specified to a user if that user is inheriting it from Group based licensing. https://docs.microsoft.com/en-us/azure/active-directory/active-directory-licensing-whatis-azure-portal * Will skip any users that don't have the specified SKU * Will skip any users that already have the SKU explicitly assigned * Will maintain the current plan state for the SKU on that user .PARAMETER Users Single UserPrincipalName, Comma seperated List, or Array of objects with UserPrincipalName property. .PARAMETER SKU SKU that should be converted to explict from inherited. .PARAMETER LogFile File to log all actions taken by the function. .OUTPUTS Log file showing all actions taken by the function. .EXAMPLE Convert-MSOLUserLicenseToExplicit -Users $UsersToConvert -SKU company:AAD_PREMIUM -logfile C:\temp\conversion.log Converts inherited AAD_PREMIUM licenses into explicit licenses for all users in $UsersToConvert and logs all actions in C:\temp\conversion.log #> param ( [Parameter(Mandatory)] [array]$Users, [Parameter(Mandatory)] [string]$LogFile, [string]$SKU ) # Make sure we have a valid log file path Test-LogPath -LogFile $LogFile # Make sure we have the connection to MSOL Test-MSOLServiceConnection # Make user our Users object is valid [array]$Users = Test-UserObject -ToTest $Users # If no value of SKU passed in then call Select-Sku to allow one to be picked if ([string]::IsNullOrEmpty($SKU)) { $SKU = Select-SKU -Message "Select SKU to Convert to Explicit:" } # If a value has been passed in verify it else { $SKU = Select-SKU -SKUToCheck $SKU } # Start Processing Write-Log ("Converting " + $SKU + " from inherited to explicit") # "Zero" out of counter [int]$i = 1 [int]$ErrorCount = 0 Foreach ($Account in $Users) { Write-Log ("==== Processing User " + $account.UserPrincipalName + " ====") # Set our skip variable to false so we process the user # Will change it to true if we need to skip the actual change $Skip = $false # Null out the variables we use [array]$CurrentDisabledPlansArray = $null $CurrentLicenseDetails = $null $MSOLUser = $null # Verify that the SKU is inherited and isn't already explicit ... don't want to overwrite any explicit settings try { # Need stop here to ensure that the error is caught in the try/catch $MSOLUser = Get-MsolUser -UserPrincipalName $Account.UserPrincipalName -ErrorAction Stop } catch { Write-Log ("[Error] - Unable to find user:`n " + $_.Exception) Write-Error ("Problem finding user " + $Account.UserPrincipalName) $ErrorCount++ $Skip = $true $MSOLUser = $null } # If the user object is null then we don't need to / can't get its license information if ($null -eq $MSOLUser) { } # Pull the license details and validate them else { $CurrentLicenseDetails = ($MSOLUser.licenses | Where-Object { $_.accountskuid -eq $SKU }) # Make sure we found the SKU on the user if ($Null -eq $CurrentLicenseDetails) { Write-Log ("[Warning] - SKU " + $SKU + " not Assigned to user " + $Account.UserPrincipalName) Write-Warning ("SKU " + $SKU + " not Assigned to user " + $Account.UserPrincipalName) # Since we can't set this we need to skip it $Skip = $true } # Make sure the SKU is inherited elseif (($CurrentLicenseDetails.GroupsAssigningLicense -contains $Users.objectid) -or ($CurrentLicenseDetails.GroupsAssigningLicense.count -le 0)) { Write-Log ("[Warning] - User " + $Account.UserPrincipalName + " already has explicit assignment for " + $SKU) Write-Warning ("User " + $Account.UserPrincipalName + " already has explicit assignment for " + $SKU) # Since it is already explict we need to skip the actual set $Skip = $true } else { # Get the currently disabled plans [array]$CurrentDisabledPlansArray = (($CurrentLicenseDetails).ServiceStatus | Where-Object { $_.ProvisioningStatus -eq "Disabled" }).serviceplan | Select-Object -ExpandProperty ServiceName Write-Log ("Disabling Plans: " + [string]$CurrentDisabledPlansArray) } } # If we set SKIP to true then we are not processing this user log it and move on if ($Skip -eq $true) { Write-Log ("Skipping user " + $Account.UserPrincipalName) } # Else we need to set the license else { # Create our License Options from the disabled plan array $LicenseOptions = Set-LicenseOption -DisabledPlansArray $CurrentDisabledPlansArray -SKU $SKU # Build, log, and run the command $cmd = "Set-MsolUserLicense -UserPrincipalName `"" + $Account.UserPrincipalName + "`" -AddLicenses " + $SKU + " -LicenseOptions `$LicenseOptions" Write-Log ("Running: " + $cmd) Invoke-Expression $cmd } # Update the progress bar and increment our counter Update-Progress -CurrentCount $i -MaxCount $Users.Count -Message "Coverting from Inherited to Explicit" $i++ } Write-Log ("Finished Adding SKU " + $SKU + " to " + $Users.Count + " Users.") If ($ErrorCount -gt 0) { Write-Log ($ErrorCount.ToString() + " ERRORS DURING PROCESSING PLEASE REVIEW ENTRIES WITH '[ERROR]' FOR MORE INFORMATION") } } |