Script repository

Microsoft 365 licenses information

Updated on: Jan 18, 2026, Views: 2658

Reports, Microsoft 365

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

    David Jenkins

    What does this line do?

    $licenseNameToSkuPartNumber = @{}  
    

    It seems like it should be populated with data later but is not.

    • Support

      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

    Ilia Goldenberg

    Hi,

    Is there a way to filter and display only the Active SKUs, excluding all Disabled, Expired, etc.?

    • Support

      Support

      Hello Ilia,

      Unfortunately, there is no such possibility.

  • Michael Kennedy

    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

      Support

      Hello Michael,

      Yes, we updated the script accordingly (the $licensseSKUs variable was added).

Got questions?

Support Questions & Answers

We use cookies to improve your experience.
By your continued use of this site you accept such use.
For more details please see our privacy policy and cookies policy.