Script repository
The script generates a report that includes information on Microsoft 365 licenses. The report will include numbers of available and used licenses in all registered tenants. To execute the script, create a report without a scope and parameters.
Parameters
$sumLicensesColumn- the identifier of the custom column that will store the full number of licenses (sum of available and used). To get the identifier:- In the Report-specific columns section, on the Columns tab, right-click the custom column.
- In the context menu, navigate to Copy and click Column ID.
- The column identifier will be copied to clipboard.
$availableLicensesColumn- the identifier of the custom column that will store the number of available licenses.$usedLicensesColumn- the identifier of the custom column that will store the number of used licenses.$tenantColumn- the identifier of the custom column that will store the name of the Microsoft 365 tenant.
$sumLicensesColumn = "{b78da4eb-6d3b-4ff3-ac1c-090d68b0498f}" # TODO: modify me
$availableLicensesColumn = "{2e05722c-9a82-4bd2-9059-5e5eee981e77}" # TODO: modify me
$usedLicensesColumn = "{51b55b9c-109f-49a6-ac8f-75c280996281}" # TODO: modify me
$tenantColumn = "{53a1bd7f-b3b3-4191-889e-948c92ed14f4}"
# Find all Microsoft 365 tenants.
$configurationContainerPath = $Context.GetWellKnownContainerPath("CloudServicesO365")
$tenantSearcher = $Context.BindToObject($configurationContainerPath)
$tenantSearcher.Criteria = New-AdmCriteria "adm-O365Tenant"
$tenantSearcher.ReferralChasing = "ADS_CHASE_REFERRALS_NEVER"
$tenantSearcher.SearchScope = "ADS_SCOPE_SUBTREE"
try
{
# Execute search
$tenantSearchResultIterator = $tenantSearcher.ExecuteSearch()
$tenants = $tenantSearchResultIterator.FetchAll()
foreach ($tenantID in $tenants)
{
# Bind to the tenant.
$tenant = $Context.BindToObject($tenantID.AdsPath)
foreach ($sku in $tenant.Skus)
{
# Get license plan display name.
if (-not([System.String]::IsNullOrEmpty($sku.CustomDisplayName)))
{
$skuDisplayName = $sku.CustomDisplayName
}
else
{
$skuDisplayName = $sku.DefaultDisplayName
}
$Context.Items.Add(-1, $skuDisplayName, "License", @{
$sumLicensesColumn = $sku.TotalUnits;
$availableLicensesColumn = $sku.TotalUnits - $sku.ConsumedUnits;
$usedLicensesColumn = $sku.ConsumedUnits;
$tenantColumn = $tenant.TenantName
})
}
}
}
finally
{
# Release resources
if ($tenantSearchResultIterator){ $tenantSearchResultIterator.Dispose() }
}
Comments 6
You must be signed in to comment.
David Jenkins
What does this line do?
It seems like it should be populated with data later but is not.
Support
Hello David,
Thank you for pointing this out. You are right, the line is not required in the script. We removed it.
Ilia Goldenberg
Hi,
Is there a way to filter and display only the Active SKUs, excluding all Disabled, Expired, etc.?
Support
Hello Ilia,
Unfortunately, there is no such possibility.
Michael Kennedy
Is there a way this script could be enhanced so it only displays certain SKUs? There are really only one or two I care to track on a daily basis about and I would like to make them into charts.
Thank you!
Support
Hello Michael,
Yes, we updated the script accordingly (the $licensseSKUs variable was added).