source/public/Get-M365LicenseAssignment.ps1
function Get-M365LicenseAssignment { [CmdletBinding(DefaultParameterSetName = 'UserId')] param ( [Parameter(Mandatory, ParameterSetName = 'UserId')] [string] $UserId, [Parameter(Mandatory, ParameterSetName = 'All')] [switch] $All, [string] $LicenseDelimiterChar = ";", [Parameter(Mandatory, ParameterSetName = 'Top')] [ValidateRange(1, 5000)] [int] $Top, [Parameter(ParameterSetName = 'Top')] [Parameter(ParameterSetName = 'All')] [switch] $IncludeGuest, [Parameter(ParameterSetName = 'Top')] [Parameter(ParameterSetName = 'All')] [string] $UsageLocation ) if (!(Get-Module Microsoft.Graph.Authentication)) { Say Error "Connect to Microsoft Graph PowerShell first with the following minimum permissions: LicenseAssignment.Read.All, User.Read.All" return $null } if (!(Get-MgContext)) { Say Error "Connect to Microsoft Graph PowerShell first with the following minimum permissions: LicenseAssignment.Read.All, User.Read.All" return $null } try { # downloads the friendly name table from Microsoft Learn GitHub. $null = GetM365ProductIdTable -ErrorAction Stop -ForceOnline } catch { SayError "There was an error getting the Sku Table from Microsoft Learn. The license names will not be resolved to friendly names." SayError $_.Exception.Message } # Build the license lookup table $subscribedSku = @{} Get-MgSubscribedSku | ForEach-Object { $subscribedSku.Add($_.SkuId, $_.SkuPartNumber) } $propertySet = @( 'Surname', 'GivenName', 'DisplayName', 'UserPrincipalName', 'State', 'UsageLocation', 'Country', 'City', 'Department', 'UserType', 'Id', 'JobTitle', 'OnPremisesSyncEnabled', 'AssignedLicenses' 'OfficeLocation', 'AccountEnabled', 'CompanyName' ) $param = @{ Property = $propertySet } switch ($PSCmdlet.ParameterSetName) { 'UserId' { $param.Add('UserId', $UserId) } 'All' { $param.Add('All', $true) } 'Top' { $param.Add('Top', $Top) } default { } } if ($PSCmdlet.ParameterSetName -ne 'UserId') { $filter = "assignedLicenses/`$count ne 0" $param.Add('Filter', $filter) $param.Add('CountVariable', 'UserCount') $param.Add('ConsistencyLevel', 'Eventual') if (-not $PSBoundParameters.ContainsKey('IncludeGuest')) { $param["Filter"] = $param["Filter"] + " and userType eq 'Member'" # SayInfo "User type filter = Member only" } else { # SayInfo "User type filter = Member and Guest" } if ($PSBoundParameters.ContainsKey('UsageLocation')) { $param["Filter"] = $param["Filter"] + " and usageLocation eq '$($UsageLocation)'" } SayInfo "Filter = $($param["Filter"])" } try { SayInfo "Getting users..." $users = Get-MgUser @param -ErrorAction Stop | Select-Object $propertySet $total = $users.Count $counter = 0 SayInfo "Total users = $($total)" ($users | Sort-Object DisplayName) | ForEach-Object { $counter++ Write-Progress -Activity "Processing Users" ` -Status "Processing [$($counter) of $($total)] $($_.DisplayName)" ` -PercentComplete (($counter / $total) * 100) [PSCustomObject]@{ 'Object id' = $_.id 'Last name' = $_.Surname 'First name' = $_.GivenName 'Display name' = $_.DisplayName 'User principal name' = $_.UserPrincipalName 'Job title' = $_.JobTitle 'Is guest user' = $(if ($_.UserType -eq 'Guest') { $true } else { $false }) 'Dir sync enabled' = $(if ($_.OnPremisesSyncEnabled) { $true } else { $false }) 'Account Enabled' = $_.AccountEnabled 'Office' = $_.OfficeLocation 'Department' = $_.Department 'Company Name' = $_.CompanyName 'City' = $_.City 'State or province' = $_.State 'Country or region' = $_.Country 'Usage location' = $_.UsageLocation 'Has license' = $(if (($_.AssignedLicenses.SkuId)) { $true } else { $false } ) 'Licenses' = $( if ($_.AssignedLicenses.SkuId) { ($_.AssignedLicenses.SkuId | ForEach-Object { $skuId = $_ ; $( $sku = GetM365ProductIdTable -SkuId $skuId if (!$sku) { $subscribedSku[$skuId] } else { $sku.SkuName } ) }) -join $LicenseDelimiterChar } ) 'AssignedProductSkus' = $( if ($_.AssignedLicenses.SkuId) { ($_.AssignedLicenses.SkuId | ForEach-Object { $skuId = $_ ; $subscribedSku[$skuId] }) -join $LicenseDelimiterChar } ) } } # Clear the progress bar after completion Write-Progress -Activity "Processing Users" -Completed } catch { SayError $_.Exception.Message return $null } } |