Script Repository


Microsoft 365 licenses assigned to dynamic distribution list members

February 24, 2021
2191

The script creates a CSV-formatted report on licenses assigned to members of a dynamic distribution list.

To generate such a report on request, you can create a custom command that runs the script on Ms-Exch-Dynamic-Distribution-List objects. For this purpose, on Step 2 of the Create Custom Command wizard, select Show all object types and Ms-Exch-Dynamic-Distribution-List.

Parameters:

  • $exchangeServer - Specifies the fully qualified domain name (FQDN) of your Exchange Server.
  • $csvFilePath - Specifies a full path to the CSV file containing the report.
  • $propertiesToExport - Specifies LDAP names of properties of the members to to include in the report.
Edit Remove
PowerShell
$exchangeServer = "exchangeserver.domain.com" # TODO: modify me
$csvFilePath = "\\SERVER\share\members.csv" # TODO: modify me
$propertiesToExport = @("Name", "Description", "Department", "mail") # TODO: modify me

try
{
    # Create a remote PowerShell session to the Exchange Server
    $session = New-PSSession -configurationname Microsoft.Exchange -connectionURI http://$exchangeServer/PowerShell
    Import-PSSession $session -DisableNameChecking -AllowClobber
    
    # Get Dynamic Distribution Group
    $group = Get-DynamicDistributionGroup -Identity "%distinguishedName%"
    
    # Get members
    $members = Get-Recipient -RecipientPreviewFilter $group.RecipientFilter -OrganizationalUnit $group.RecipientContainer
    
    # Build search filter to find all members in AD
    $filter = New-Object "System.Text.StringBuilder"
    [void]$filter.Append("(|")
    
    foreach ($member in $members)
    {
        $guid = [Guid]$member.Guid
        [void]$filter.Append([Softerra.Adaxes.Ldap.FilterBuilder]::Create("objectGuid", $guid))
    }
    
    [void]$filter.Append(")")
}
finally
{
    # Release resources
    if ($session) { Remove-PSSession $session }
}

# Find members in AD
$domainName = $Context.GetObjectDomain("%distinguishedName%")
$searcher = $Context.BindToObject("Adaxes://$domainName/RootDSE")
$searcher.SearchFilter = $filter.ToString()
$searcher.PageSize = 500
$searcher.SetPropertiesToLoad($propertiesToExport)

try
{
    $searchResultIterator = $searcher.ExecuteSearch()
    $searchResults = $searchResultIterator.FetchAll()
        
    $records = @()
    foreach ($searchResult in $searchResults)
    {
        $record = New-Object PSObject
        foreach ($propertyName in $propertiesToExport)
        {
            $record | Add-Member -Name $propertyName -Value $searchResult.Properties[$propertyName].Value -MemberType NoteProperty
        }

        $record | Add-Member -Name "IsLicensed" -Value $NULL -MemberType NoteProperty
        
        # Bind to member
        $member = $Context.BindToObject($searchResult.AdsPath)

        if ($member.Class -eq "User")
        {
            $isLicensed = $False
            try
            {
                # Get Microsoft 365 properties
                $microsoft365Properties = $member.GetOffice365Properties()
            }
            catch
            {
                $microsoft365Properties = $NULL # No Microsoft 365 account
            }
            
            if ($microsoft365Properties -ne $NULL)
            {
                # Check assigned licenses
                $licenses = $microsoft365Properties.Licenses

                foreach ($license in $licenses)
                {
                    if ($license.Assigned)
                    {
                        $isLicensed = $True
                        break
                    }
                }
            }
            $record.IsLicensed = $isLicensed
        }
        $records += $record
    }
    
    # Export members
    $records | Export-Csv -NoTypeInformation -Path $csvFilePath
}
finally
{
    # Release resources used by search
    if ($searchResultIterator) { $searchResultIterator.Dispose() }
}


Comments ( 0 )
No results found.
Leave a comment

Related Scripts