Src/Private/Get-AbrIntuneCloudPC.ps1

function Get-AbrIntuneCloudPC {
    <#
    .SYNOPSIS
    Documents Windows 365 / Cloud PC configuration in Microsoft Intune.
    .DESCRIPTION
        Collects and reports on:
          - Cloud PC Provisioning Policies (OS image, network, region, assignment)
          - Cloud PC User Settings (local admin, restore points, weekly reset)
    .NOTES
        Version: 0.1.0
        Author: Pai Wei Sing
    #>

    [CmdletBinding()]
    param (
        [Parameter(Position = 0, Mandatory)]
        [string]$TenantId
    )

    begin {
        Write-PScriboMessage -Message "Collecting Windows 365 Cloud PC configuration for $TenantId."
        Show-AbrDebugExecutionTime -Start -TitleMessage 'Cloud PC'
    }

    process {
        Section -Style Heading2 'Windows 365 / Cloud PC' {
            Paragraph "The following section documents Windows 365 Cloud PC configuration for tenant $TenantId."
            BlankLine

            $foundAny = $false

            #region Provisioning Policies
            try {
                Write-Host " - Retrieving Cloud PC Provisioning Policies..."
                $ProvResp = Invoke-MgGraphRequest -Method GET `
                    -Uri "$($script:GraphEndpoint)/beta/deviceManagement/virtualEndpoint/provisioningPolicies?`$expand=assignments" `
                    -ErrorAction SilentlyContinue
                $ProvPolicies = $ProvResp.value

                if ($ProvPolicies -and @($ProvPolicies).Count -gt 0) {
                    $foundAny = $true
                    Section -Style Heading3 'Provisioning Policies' {
                        BlankLine
                        $ProvObj = [System.Collections.ArrayList]::new()
                        foreach ($Policy in ($ProvPolicies | Sort-Object displayName)) {
                            $assignResolved = Resolve-IntuneAssignments -Assignments $Policy.assignments

                            $provInObj = [ordered] @{
                                'Policy Name'       = $Policy.displayName
                                'Cloud PC Size'     = if ($Policy.cloudPcNamingTemplate) { $Policy.cloudPcNamingTemplate } else { '--' }
                                'Domain Join Type'  = if ($Policy.domainJoinConfiguration.domainJoinType) { $Policy.domainJoinConfiguration.domainJoinType } else { '--' }
                                'Image Type'        = if ($Policy.imageType) { $Policy.imageType } else { '--' }
                                'Windows Autopatch' = if ($null -ne $Policy.windowsAutopatch) { $Policy.windowsAutopatch } else { '--' }
                                'Included Groups'   = $assignResolved.IncludedGroups
                                'Excluded Groups'   = if ($script:ShowExcludedGroups) { $assignResolved.ExcludedGroups } else { $null }
                                'Last Modified'     = if ($Policy.lastModifiedDateTime) { ([datetime]$Policy.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' }
                            }

                            $ProvObj.Add([pscustomobject](ConvertTo-HashToYN $provInObj)) | Out-Null
                        }

                        $null = (& {
                            if ($HealthCheck.Intune.CloudPC) {
                                $null = ($ProvObj | Where-Object { $_.'Included Groups' -eq '--' } | Set-Style -Style Warning | Out-Null)
                            }
                        })

                        $ProvTableParams = @{ Name = "Cloud PC Provisioning Policies - $TenantId"; ColumnWidths = 20, 14, 14, 10, 10, 22, 5, 5 }
                        if ($Report.ShowTableCaptions) { $ProvTableParams['Caption'] = "- $($ProvTableParams.Name)" }
                        $ProvObj | Table @ProvTableParams

                        if (Get-IntuneExcelSheetEnabled -SheetKey 'CloudPCProvisioning') { $script:ExcelSheets['Cloud PC Provisioning'] = $ProvObj }
                        if (Get-IntuneBackupSectionEnabled -SectionKey 'CloudPCProvisioning') { $script:BackupData['CloudPCProvisioning'] = $ProvPolicies }
                    }
                }
            } catch {
                if (Test-AbrGraphForbidden -ErrorRecord $_) {
                    Write-AbrPermissionError -Section 'Cloud PC Provisioning Policies' -RequiredRole 'Intune Service Administrator or Global Administrator (requires CloudPC.Read.All scope)'
                } else {
                    Write-AbrSectionError -Section 'Cloud PC Provisioning Policies' -Message "$($_.Exception.Message)"
                }
            }
            #endregion

            #region User Settings
            try {
                Write-Host " - Retrieving Cloud PC User Settings..."
                $UserSetResp = Invoke-MgGraphRequest -Method GET `
                    -Uri "$($script:GraphEndpoint)/beta/deviceManagement/virtualEndpoint/userSettings?`$expand=assignments" `
                    -ErrorAction SilentlyContinue
                $UserSettings = $UserSetResp.value

                if ($UserSettings -and @($UserSettings).Count -gt 0) {
                    $foundAny = $true
                    Section -Style Heading3 'User Settings' {
                        BlankLine
                        $UsObj = [System.Collections.ArrayList]::new()
                        foreach ($Setting in ($UserSettings | Sort-Object displayName)) {
                            $assignResolved = Resolve-IntuneAssignments -Assignments $Setting.assignments

                            $usInObj = [ordered] @{
                                'Setting Name'           = $Setting.displayName
                                'Local Admin Enabled'    = $Setting.localAdminEnabled
                                'Reset Enabled'          = $Setting.resetEnabled
                                'Restore Point Freq'     = if ($Setting.restorePointSetting.frequencyInHours) { "$($Setting.restorePointSetting.frequencyInHours)h" } else { '--' }
                                'User to AAD Sync'       = if ($null -ne $Setting.selfServiceEnabled) { $Setting.selfServiceEnabled } else { '--' }
                                'Included Groups'        = $assignResolved.IncludedGroups
                                'Excluded Groups'        = if ($script:ShowExcludedGroups) { $assignResolved.ExcludedGroups } else { $null }
                                'Last Modified'          = if ($Setting.lastModifiedDateTime) { ([datetime]$Setting.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' }
                            }

                            $UsObj.Add([pscustomobject](ConvertTo-HashToYN $usInObj)) | Out-Null
                        }

                        $UsTableParams = @{ Name = "Cloud PC User Settings - $TenantId"; ColumnWidths = 18, 12, 11, 12, 12, 23, 7, 5 }
                        if ($Report.ShowTableCaptions) { $UsTableParams['Caption'] = "- $($UsTableParams.Name)" }
                        $UsObj | Table @UsTableParams

                        if (Get-IntuneExcelSheetEnabled -SheetKey 'CloudPCUserSettings') { $script:ExcelSheets['Cloud PC User Settings'] = $UsObj }
                        if (Get-IntuneBackupSectionEnabled -SectionKey 'CloudPCUserSettings') { $script:BackupData['CloudPCUserSettings'] = $UserSettings }
                    }
                }
            } catch {
                if (Test-AbrGraphForbidden -ErrorRecord $_) {
                    Write-AbrPermissionError -Section 'Cloud PC User Settings' -RequiredRole 'Intune Service Administrator (requires Windows 365 licence)'
                } else {
                    Write-AbrSectionError -Section 'Cloud PC User Settings' -Message "$($_.Exception.Message)"
                }
            }
            #endregion

            if (-not $foundAny) {
                Paragraph "No Windows 365 Cloud PC configuration found in tenant $TenantId. Windows 365 requires a Cloud PC licence."
            }
        }
    }

    end {
        Show-AbrDebugExecutionTime -End -TitleMessage 'Cloud PC'
    }
}