Public/Get-IntuneAllDevicesAssignment.ps1

function Get-IntuneAllDevicesAssignment {
    [CmdletBinding()]
    param (
        [Parameter()]
        [switch]$ExportToCSV,

        [Parameter()]
        [string]$ExportPath,

        [Parameter()]
        [string]$ScopeTagFilter
    )

    Write-Host "Fetching all 'All Devices' assignments..." -ForegroundColor Green
    $exportData = [System.Collections.ArrayList]::new()

    # Local display-name helpers preserving the historical per-category fallback quirks.
    function Get-NamePreferringName { param($Item) if ([string]::IsNullOrWhiteSpace($Item.name)) { $Item.displayName } else { $Item.name } }
    function Get-NamePreferringDisplayName { param($Item) if ([string]::IsNullOrWhiteSpace($Item.displayName)) { $Item.name } else { $Item.displayName } }
    function Get-NameWithUnnamedFallback {
        param($Item, [string]$Fallback)
        if (-not [string]::IsNullOrWhiteSpace($Item.displayName)) { $Item.displayName }
        elseif (-not [string]::IsNullOrWhiteSpace($Item.name)) { $Item.name }
        else { $Fallback }
    }

    # UserContext is the registry audience whose category set covers this cmdlet
    # (Applications included, no ES exclusion on Settings Catalog). Local adjustments
    # reproduce the pre-migration behavior of this cmdlet: Autopilot/ESP profiles ARE
    # fetched here (UserContext registers them bucket-only for export parity) and the
    # Windows 365 Cloud PC categories are not part of this cmdlet.
    $categoryById = @{}
    foreach ($category in (Get-IntuneCategoryDefinition -Audience 'UserContext')) { $categoryById[$category.Id] = $category }
    foreach ($id in @('DeploymentProfiles', 'ESPProfiles')) { $categoryById[$id].BucketOnly = $false }

    # Fetch order matches the pre-migration cmdlet (16 categories).
    $scanCategories = foreach ($id in @(
            'DeviceConfigurations', 'SettingsCatalog', 'CompliancePolicies', 'AppProtectionPolicies',
            'AppConfigurationPolicies', 'Applications', 'PlatformScripts', 'HealthScripts',
            'DeploymentProfiles', 'ESPProfiles',
            'ESAntivirus', 'ESDiskEncryption', 'ESFirewall', 'ESEndpointDetection', 'ESAttackSurface', 'ESAccountProtection')) {
        $categoryById[$id]
    }

    $processEntity = {
        param($ctx)

        $entity = $ctx.Entity

        if ($ctx.Category.Kind -eq 'MobileApps') {
            # Historical app handling: only the first 'All Devices' assignment counts,
            # and the app lands in the bucket matching that assignment's intent.
            foreach ($assignment in $ctx.RawAssignments) {
                if ($assignment.target.'@odata.type' -eq '#microsoft.graph.allDevicesAssignmentTarget') {
                    $suffix = Format-AssignmentFilter -FilterId $assignment.target.deviceAndAppManagementAssignmentFilterId -FilterType $assignment.target.deviceAndAppManagementAssignmentFilterType
                    $appWithReason = $entity.PSObject.Copy()
                    $appWithReason | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue "All Devices$suffix" -Force
                    switch ($assignment.intent) {
                        'required' { $ctx.Buckets['AppsRequired'].Add($appWithReason); break }
                        'available' { $ctx.Buckets['AppsAvailable'].Add($appWithReason); break }
                        'uninstall' { $ctx.Buckets['AppsUninstall'].Add($appWithReason); break }
                    }
                    break
                }
            }
            return
        }

        $reason = if ($null -ne $ctx.RawAssignments) {
            # App Protection policies and legacy intent-based ES policies: historical
            # wording built the filter suffix from the first raw 'All Devices' target.
            $allDevicesAssignment = $ctx.RawAssignments |
                Where-Object { $_.target.'@odata.type' -eq '#microsoft.graph.allDevicesAssignmentTarget' } |
                Select-Object -First 1
            if ($allDevicesAssignment) {
                $suffix = Format-AssignmentFilter -FilterId $allDevicesAssignment.target.deviceAndAppManagementAssignmentFilterId -FilterType $allDevicesAssignment.target.deviceAndAppManagementAssignmentFilterType
                "All Devices$suffix"
            }
        }
        else {
            Get-AllTargetReason -Assignments $ctx.Assignments -TargetReason 'All Devices'
        }

        if ($reason) {
            $entity | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $reason -Force
            $ctx.Buckets[$ctx.Category.BucketKeys[0]].Add($entity)
        }
    }

    $scanResult = Invoke-IntuneCategoryScan -Categories $scanCategories -ProcessEntity $processEntity -ShowProgress
    $allDevicesAssignments = $scanResult.Buckets

    # Apply scope tag filter if specified
    if ($ScopeTagFilter) {
        foreach ($key in @($allDevicesAssignments.Keys)) {
            $allDevicesAssignments[$key] = @(Filter-ByScopeTag -Items $allDevicesAssignments[$key] -FilterTag $ScopeTagFilter -ScopeTagLookup $script:ScopeTagLookup)
        }
    }

    # Display results
    Write-Host "`nPolicies Assigned to All Devices:" -ForegroundColor Green

    $displaySpecs = @(
        @{ Bucket = 'DeviceConfigs'; Header = 'Device Configurations'; Empty = 'Device Configurations'; Line = { param($item) "Device Configuration Name: $(Get-NamePreferringName $item), Platform: $(Get-PolicyPlatform -Policy $item), Configuration ID: $($item.id)" } }
        @{ Bucket = 'SettingsCatalog'; Header = 'Settings Catalog Policies'; Empty = 'Settings Catalog Policies'; Line = { param($item) "Settings Catalog Policy Name: $(Get-NamePreferringName $item), Policy ID: $($item.id)" } }
        @{ Bucket = 'CompliancePolicies'; Header = 'Compliance Policies'; Empty = 'Compliance Policies'; Line = { param($item) "Compliance Policy Name: $(Get-NamePreferringName $item), Platform: $(Get-PolicyPlatform -Policy $item), Policy ID: $($item.id)" } }
        @{ Bucket = 'AppProtectionPolicies'; Header = 'App Protection Policies'; Empty = 'App Protection Policies'; Line = {
                param($item)
                $policyType = switch ($item.'@odata.type') {
                    "#microsoft.graph.androidManagedAppProtection" { "Android" }
                    "#microsoft.graph.iosManagedAppProtection" { "iOS" }
                    "#microsoft.graph.windowsManagedAppProtection" { "Windows" }
                    default { "Unknown" }
                }
                "App Protection Policy Name: $($item.displayName), Policy ID: $($item.id), Type: $policyType"
            }
        }
        @{ Bucket = 'AppConfigurationPolicies'; Header = 'App Configuration Policies'; Empty = 'App Configuration Policies'; Line = { param($item) "App Configuration Policy Name: $(Get-NamePreferringName $item), Policy ID: $($item.id)" } }
        @{ Bucket = 'PlatformScripts'; Header = 'Platform Scripts'; Empty = 'Platform Scripts'; Line = { param($item) "Script Name: $(Get-NamePreferringName $item), Script ID: $($item.id)" } }
        @{ Bucket = 'HealthScripts'; Header = 'Proactive Remediation Scripts'; Empty = 'Proactive Remediation Scripts'; Line = { param($item) "Script Name: $(Get-NamePreferringName $item), Script ID: $($item.id)" } }
        @{ Bucket = 'AppsRequired'; Header = 'Required Apps'; Empty = 'Required Apps'; Line = { param($item) "App Name: $($item.displayName), App ID: $($item.id)" } }
        @{ Bucket = 'AppsAvailable'; Header = 'Available Apps'; Empty = 'Available Apps'; Line = { param($item) "App Name: $($item.displayName), App ID: $($item.id)" } }
        @{ Bucket = 'AppsUninstall'; Header = 'Uninstall Apps'; Empty = 'Uninstall Apps'; Line = { param($item) "App Name: $($item.displayName), App ID: $($item.id)" } }
        @{ Bucket = 'AntivirusProfiles'; Header = 'Endpoint Security - Antivirus Profiles'; Empty = 'Antivirus Profiles'; Line = { param($item) "Antivirus Profile Name: $($item.displayName), Profile ID: $($item.id)" } }
        @{ Bucket = 'DiskEncryptionProfiles'; Header = 'Endpoint Security - Disk Encryption Profiles'; Empty = 'Disk Encryption Profiles'; Line = { param($item) "Disk Encryption Profile Name: $($item.displayName), Profile ID: $($item.id)" } }
        @{ Bucket = 'FirewallProfiles'; Header = 'Endpoint Security - Firewall Profiles'; Empty = 'Firewall Profiles'; Line = { param($item) "Firewall Profile Name: $($item.displayName), Profile ID: $($item.id)" } }
        @{ Bucket = 'EndpointDetectionProfiles'; Header = 'Endpoint Security - EDR Profiles'; Empty = 'EDR Profiles'; Line = { param($item) "EDR Profile Name: $(Get-NameWithUnnamedFallback $item 'Unnamed EDR Profile'), Profile ID: $($item.id)" } }
        @{ Bucket = 'AttackSurfaceProfiles'; Header = 'Endpoint Security - ASR Profiles'; Empty = 'ASR Profiles'; Line = { param($item) "ASR Profile Name: $($item.displayName), Profile ID: $($item.id)" } }
        @{ Bucket = 'AccountProtectionProfiles'; Header = 'Endpoint Security - Account Protection Profiles'; Empty = 'Account Protection Profiles'; Line = { param($item) "Account Protection Profile Name: $(Get-NameWithUnnamedFallback $item 'Unnamed Account Protection Profile'), Profile ID: $($item.id)" } }
        @{ Bucket = 'DeploymentProfiles'; Header = 'Autopilot Deployment Profiles'; Empty = 'Autopilot Deployment Profiles'; Line = { param($item) "Deployment Profile Name: $(Get-NamePreferringDisplayName $item), Profile ID: $($item.id)" } }
        @{ Bucket = 'ESPProfiles'; Header = 'Enrollment Status Page Profiles'; Empty = 'Enrollment Status Page Profiles'; Line = { param($item) "Enrollment Status Page Name: $(Get-NamePreferringDisplayName $item), Profile ID: $($item.id)" } }
    )

    foreach ($spec in $displaySpecs) {
        Write-Host "`n------- $($spec.Header) -------" -ForegroundColor Cyan
        $items = @($allDevicesAssignments[$spec.Bucket])
        if ($items.Count -eq 0) {
            Write-Host "No $($spec.Empty) assigned to All Devices" -ForegroundColor Gray
            continue
        }
        foreach ($item in $items) {
            Write-Host (& $spec.Line $item) -ForegroundColor White
        }
    }

    # Export rows in the pre-migration CSV order (apps after scripts, Autopilot/ESP last).
    $exportCategories = foreach ($id in @(
            'DeviceConfigurations', 'SettingsCatalog', 'CompliancePolicies', 'AppProtectionPolicies',
            'AppConfigurationPolicies', 'PlatformScripts', 'HealthScripts', 'Applications',
            'ESAntivirus', 'ESDiskEncryption', 'ESFirewall', 'ESEndpointDetection', 'ESAttackSurface', 'ESAccountProtection',
            'DeploymentProfiles', 'ESPProfiles')) {
        $categoryById[$id]
    }
    Add-CategoryExportData -ExportData $exportData -Categories $exportCategories -Buckets $allDevicesAssignments -AssignmentReason "All Devices"

    # Export results if requested
    Export-ResultsIfRequested -ExportData $exportData -DefaultFileName "IntuneAllDevicesAssignments.csv" -ForceExport:$ExportToCSV -CustomExportPath $ExportPath -ExportToCSV:$ExportToCSV -ParameterMode:$parameterMode
}