Hello, today I am sharing with you an interesting Office 365 script that I hope will help you. This script will tell you how licenses are assigned to a set of user in your Office 365 tenant : Direct or Inherited ?
My script consists of 2 parts, the first determines License Plans assigned to a user account, the second one dertermines the Licenses paths (Direct or Inherited).
function Get-LicensePlan {
param (
[Parameter(Mandatory=$true)]
[String]$SkuId,
[Parameter(mandatory=$true)]
[String]$TenantName
)
Switch($SkuId){
"$($TenantName):AAD_PREMIUM" {return "AAD Premium P1"}
"$($TenantName):AX7_USER_TRIAL" {return "D_AX7.0 TRIAL"}
"$($TenantName):DYN365_ENTERPRISE_P1_IW" {return "D365 ETR P1"}
"$($TenantName):DYN365_RETAIL_TRIAL" {return "D365 CRM TRIAL"}
"$($TenantName):EMS" {return "EMS_E3"}
"$($TenantName):EMSPREMIUM" {return "EMS_E5"}
"$($TenantName):DESKLESSPACK" {return "F1"}
"$($TenantName):STANDARDPACK" {return "E1"}
"$($TenantName):ENTERPRISEPACK" {return "E3"}
"$($TenantName):ENTERPRISEPREMIUM" {return "E5"}
"$($TenantName):FLOW_FREE" {return "FLOW FREE"}
"$($TenantName):INTUNE_A_VL" {return "INTUNE"}
"$($TenantName):MCOMEETADV" {return "SFB PSTN Conf"}
"$($TenantName):MICROSOFT_BUSINESS_CENTER" {return "MBC"}
"$($TenantName):POWER_BI_PRO" {return "PBI PRO"}
"$($TenantName):POWER_BI_STANDARD" {return "PBI STD"}
"$($TenantName):POWERAPPS_INDIVIDUAL_USER" {return "PAPPS IND User"}
"$($TenantName):POWERAPPS_VIRAL" {return "PAPPS and LOGIC FLOW"}
"$($TenantName):PROJECTPREMIUM" {return "PJ Online"}
"$($TenantName):STREAM" {return "STREAM"}
"$($TenantName):VISIOONLINE_PLAN1" {return "VISIO P1"}
"$($TenantName):WACONEDRIVESTANDARD" {return "OD P1"}
"$($TenantName):WIN_DEF_ATP" {return "WDF ATP"}
default {return $SkuId.Replace("$($TenantName):","")}
}
}
With the function Get-LicensePlan, we know what licenses are assigned to a user based on the SkuId. The following second function Get-LAPATH (Get-LicenseAssingmentPaths) will tell us if the licenses are Direct assigned or Inherited from a group.
function Get-LAPATH{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]$UPN
)
Begin{
Get-Date
Write-Host "## Data processing stated at $(Get-date)" -ForegroundColor Yellow
Write-Host ""
$TenantName = ((Get-MsolAccountSku).AccountSkuId[0] -split(':'))[0]
}
Process{
Write-Host ""
Write-Host "Working on $UPN" -ForegroundColor Green
$User = Get-MsolUser -UserPrincipalName $UPN
#Getting assignment paths
$LicensesTab = $null
$LicensePlan = $null
$LicTabCount = 0
$LicensesTab = $User.Licenses | Select-Object AccountSkuId, GroupsAssigningLicense
if($LicensesTab){
Write-Host "License Enabled : True" -ForegroundColor Yellow
$i = 0 #(Measure-Object -InputObject $LicensesTab).Count
$LicTabCount = $LicensesTab.AccountSkuId.Count
Do{
#Getting License Plan
$LicensePlan = Get-LicensePlan -SkuId $LicensesTab[$i].AccountSkuId -TenantName $TenantName
#Getting License Paths
[System.Collections.ArrayList]$LicensePath = @()
if($LicensesTab[$i].GroupsAssigningLicense){
foreach ($Guid in $LicensesTab[$i].GroupsAssigningLicense.guid){
if($Guid -eq $User.ObjectId.Guid){
$LicensePath.Add("Direct") | Out-Null
}
else{
$LicensePath.Add((Get-MsolGroup -ObjectId $Guid).DisplayName) | Out-Null
}
}
}
else{
$LicensePath.Add("Direct") | Out-Null
}
Write-Host "$LicensePlan : $([String]::Join(",",$LicensePath.ToArray()))" -ForegroundColor Yellow
$i++
}
While ($i -ne $LicTabCount)
}
else {
Write-Host "License Enabled : false" -ForegroundColor Red
}
}
End{
Write-Host ""
Write-Host "## Data Processing ended on $(Get-Date)" -ForegroundColor Yellow
}
}
Now that everything is set, let’s talk about how to use this script to achieve your goal. Of course, for running this script, you need to have Microsoft Online Services PowerShell installed on your computer (PowerShell Module For Office 365) and a read access permissions on your Office 365 Admin portal to see users configuration, ideally User Management Role.
- To see Office 365 license assginment paths for one user
"<UserPrincipalName>" | Get-LAPATH

The user james.bond@acidalien.fr has 3 licenses plans assigned:
- FLOW FREE inherited from the license group GRP-FLOW-FREE
- FLOW FREE directly assigned
- DEVELOPERPACK directly assigned
- To see Office 365 license assignment paths for several users
From a Powershell table
"User1 upn" ,"User2 upn","..." | Get-LAPATH

From a file containing the list of UserPrincipalName :

Get-Content -Path <File path.txt> | Get-LAPATH

Et voilà 🙂
Hi, just a question, how can i export the output to csv easily from this script?
LikeLike
I have tried to use your script above but it returns no results. Where should the script be stored as I am not familiar with function scripts?
LikeLiked by 1 person
Hello Doug,
1/ If you have not installed the msolonline powershelle module, use this link : https://docs.microsoft.com/en-us/powershell/azure/active-directory/install-msonlinev1?view=azureadps-1.0
2/ Open a powershell console, Run the cmdlet Connect-MsolService to connect msolonline sevice
3/ Copy/pass the two scripts functions Get-LicensePlan and Get-LAPATH in order to upload the functions
4/ Run the cmdlet in two ways :
– using upns
“” ,””,”…” | Get-LAPATH
-using a txt file containing upns
Get-Content -Path | Get-LAPATH
Hope it’s helped
LikeLike
Thanks for the quick reply. I have MSOnline module installed. When I execute it the I just get a command prompt.
PS C:\scripts\LicensePath> Connect-MsolService
PS C:\scripts\LicensePath> “testuser@mydomain.com” | Get-LAPath
PS C:\scripts\LicensePath>
I guess I don’t understand ‘3/ Copy/pass the two scripts functions Get-LicensePlan and Get-LAPATH in order to upload the functions’
I have created 2 .ps1 scripts, Get-LicensePlan.ps1 and Get-LAPath.ps1 and saved them to my c:\scripts\LicensePath folder.
I cd to that folder and execute the command. Should they be saved in another location?
Sorry for the questions I am still learning PS and haven’t dealt with these types of scripts before.
LikeLike
You don’t need to save the script in .ps1 file
0/ connect-msolservice
1/ copy the script : function Get-LicensePlan{…} and pass directly in your powershell console
2/ copy the script : function Get-LAPATH{…} and pass it directly in your powershell console
3/then run the cmdlet testuser@mydomain.com | Get-LAPath
LikeLike
Thank you. I finally got it to work.
I copied/pasted the code into my ps session and was able to run the cmdlet testuser@mydomain.com | Get-LAPath and it returned the results like in your screenshots. YAY!!!
I also figured out how to save them as .psm1 files and import them and it worked that way too.
Much appreciated!!! You totally rock!!!
LikeLike
You are welcome, thank you for your feedback !!!
LikeLike
How can I extract the licenses assignment for all users?
LikeLike
To export, use this version of the script:
function Get-LicensePlan {
param (
[Parameter(Mandatory=$true)]
[String]$SkuId,
[Parameter(mandatory=$true)]
[String]$TenantName
)
Switch($SkuId){
“$($TenantName):AAD_PREMIUM” {return “AAD Premium P1”}
“$($TenantName):AX7_USER_TRIAL” {return “D_AX7.0 TRIAL”}
“$($TenantName):DYN365_ENTERPRISE_P1_IW” {return “D365 ETR P1”}
“$($TenantName):DYN365_RETAIL_TRIAL” {return “D365 CRM TRIAL”}
“$($TenantName):EMS” {return “EMS_E3”}
“$($TenantName):EMSPREMIUM” {return “EMS_E5”}
“$($TenantName):DESKLESSPACK” {return “F1”}
“$($TenantName):STANDARDPACK” {return “E1”}
“$($TenantName):ENTERPRISEPACK” {return “E3”}
“$($TenantName):ENTERPRISEPREMIUM” {return “E5”}
“$($TenantName):FLOW_FREE” {return “FLOW FREE”}
“$($TenantName):INTUNE_A_VL” {return “INTUNE”}
“$($TenantName):MCOMEETADV” {return “SFB PSTN Conf”}
“$($TenantName):MICROSOFT_BUSINESS_CENTER” {return “MBC”}
“$($TenantName):POWER_BI_PRO” {return “PBI PRO”}
“$($TenantName):POWER_BI_STANDARD” {return “PBI STD”}
“$($TenantName):POWERAPPS_INDIVIDUAL_USER” {return “PAPPS IND User”}
“$($TenantName):POWERAPPS_VIRAL” {return “PAPPS and LOGIC FLOW”}
“$($TenantName):PROJECTPREMIUM” {return “PJ Online”}
“$($TenantName):STREAM” {return “STREAM”}
“$($TenantName):VISIOONLINE_PLAN1” {return “VISIO P1”}
“$($TenantName):WACONEDRIVESTANDARD” {return “OD P1”}
“$($TenantName):WIN_DEF_ATP” {return “WDF ATP”}
default {return $SkuId.Replace(“$($TenantName):”,””)}
}
}
function Get-LAPATH{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]$UPN,
[Parameter(Mandatory=$true)]
[string]$ExportPath
)
Begin{
Get-Date
Write-Host “## Data processing stated at $(Get-date)” -ForegroundColor Blue
Write-Host “”
$TenantName = ((Get-MsolAccountSku)[0].AccountSkuId -split(‘:’))[0]
}
Process{
Write-Host “”
Write-Host “Working on $UPN” -ForegroundColor Green
$User = Get-MsolUser -UserPrincipalName $UPN
#Getting assignment paths
$LicensesTab = $null
$LicensePlan = $null
$LicTabCount = 0
$LicensesTab = $User.Licenses | Select-Object AccountSkuId, GroupsAssigningLicense
if($LicensesTab){
Write-Host “License Enabled : True” -ForegroundColor Yellow
$i = 0 #(Measure-Object -InputObject $LicensesTab).Count
$LicTabCount = $LicensesTab.AccountSkuId.Count
Do{
#Getting License Plan
$LicensePlan = Get-LicensePlan -SkuId $LicensesTab[$i].AccountSkuId -TenantName $TenantName
#Getting License Paths
[System.Collections.ArrayList]$LicensePath = @()
if($LicensesTab[$i].GroupsAssigningLicense){
foreach ($Guid in $LicensesTab[$i].GroupsAssigningLicense.guid){
if($Guid -eq $User.ObjectId.Guid){
$LicensePath.Add(“Direct”) | Out-Null
}
else {
$LicensePath.Add((Get-MsolGroup -ObjectId $Guid).DisplayName) | Out-Null
}
}
}
else{
$LicensePath.Add(“Direct”) | Out-Null
}
Write-Host $LicensePath
Write-Host “$LicensePlan : $($LicensePath.ToArray() -join “,”)” -ForegroundColor Yellow #$([String]::Join(“,”,$LicensePath.ToArray()))
New-Object -TypeName PSObject -Property @{
“UserPrincipalName” = $UPN
“LicensePlan” = $LicensePlan
“AssignmentPath” = $($LicensePath.ToArray() -join “,”)
} | Export-Csv -Path $ExportPath -Encoding UTF8 -Delimiter “;” -NoTypeInformation -Append
$i++
}
while ($i -ne $LicTabCount)
}
else {
Write-Host “License Enabled : false” -ForegroundColor Red
New-Object -TypeName PSObject -Property @{
“UserPrincipalName” = $UPN
“LicensePlan” = “”
“AssignmentPath” = “”
} | Export-Csv -Path $ExportPath -Encoding UTF8 -Delimiter “;” -NoTypeInformation -Append
}
}
End{
Write-Host “”
Write-Host “## Data Processing ended on $(Get-Date)” -ForegroundColor Blue
}
}
“upn1″,”upn2” | Get-LAPATH -ExportPath “c:\file.csv”
LikeLike
how can I use this script to export all users instead of upn1, upn2?
LikeLike
This script made my day!! Thank you for creating this. Worked very well.
LikeLike
Thank you, you help us very much
LikeLike