Public/Get-CloudPC.ps1

function Get-CloudPC {
    <#
    .SYNOPSIS
        Returns Windows 365 Cloud PCs in the tenant.

    .DESCRIPTION
        Thin, fast wrapper over /beta/deviceManagement/virtualEndpoint/cloudPCs that returns
        normalized PSCustomObjects (PSTypeName = 'WindowsCloudPC.CloudPC') suitable for piping
        into Get-CloudPCUsage, Where-Object, Format-Table, etc. The raw Graph object is preserved
        on the .Raw property.

        Name is the Cloud PC displayName, which is the value changed by Rename-CloudPC.
        ManagedDeviceName is returned separately because it can remain unchanged after a
        Cloud PC display name rename.

        The request selects connectivityResult and sends
        Prefer: include-unknown-enum-members so Graph returns evolvable enum
        values such as inUse and underServiceMaintenance.

    .PARAMETER ProvisioningPolicyId
        Filter to a single provisioning policy.

    .PARAMETER UserPrincipalName
        Filter to Cloud PCs assigned to a specific user (dedicated only — Graph cannot filter
        sharedDeviceDetail by user).

    .PARAMETER Id
        Return a single Cloud PC by Cloud PC ID.

    .PARAMETER Name
        Filter by Cloud PC display name or managed device name. Exact matches are used
        unless the value contains wildcard characters. Aliases: DisplayName, ManagedDeviceName.

    .PARAMETER Type
        Shared, Dedicated, or All (default).

    .EXAMPLE
        Get-CloudPC | Format-Table Name,ProvisioningType,AssignedUserUpn,ConnectivityStatus

    .EXAMPLE
        Get-CloudPC -ProvisioningPolicyId 8e8a545f-6168-4472-9466-9f05520a5eb3 -Type Shared

    .EXAMPLE
        Get-CloudPC -Id '95194d88-cec5-4b65-af62-26dbd1814364'

    .EXAMPLE
        Get-CloudPC -Name 'CFD-brad-*'
    #>

    [CmdletBinding()]
    [OutputType('WindowsCloudPC.CloudPC')]
    param(
        [Parameter(ValueFromPipelineByPropertyName)]
        [string]$ProvisioningPolicyId,

        [Parameter(ValueFromPipelineByPropertyName)]
        [string]$UserPrincipalName,

        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('CloudPcId')]
        [string]$Id,

        [Alias('DisplayName','ManagedDeviceName')]
        [SupportsWildcards()]
        [string]$Name,

        [ValidateSet('Shared','Dedicated','All')]
        [string]$Type = 'All'
    )

    begin {
        Connect-CloudPC | Out-Null
    }

    process {
        if ($Id -and $Name) {
            throw "Get-CloudPC: use either -Id or -Name, not both."
        }

        $filters = @("servicePlanType eq 'enterprise'")
        if ($ProvisioningPolicyId) { $filters += "provisioningPolicyId eq '$ProvisioningPolicyId'" }
        if ($UserPrincipalName)    { $filters += "userPrincipalName eq '$UserPrincipalName'" }
        $filter = ($filters -join ' and ')

        $select = @(
            'id','managedDeviceId','managedDeviceName','displayName','userPrincipalName',
            'status','provisioningType','provisioningPolicyId','provisioningPolicyName',
            'servicePlanName','sharedDeviceDetail','connectivityResult','lastModifiedDateTime',
            'aadDeviceId'
        ) -join ','

        $uri = 'https://graph.microsoft.com/beta/deviceManagement/virtualEndpoint/cloudPCs' +
               '?$filter=' + [uri]::EscapeDataString($filter) +
               '&$select=' + [uri]::EscapeDataString($select) +
               '&$top=50' +
               '&$orderBy=lastModifiedDateTime%20desc'

        $headers = @{
            ConsistencyLevel = 'eventual'
            Prefer           = 'include-unknown-enum-members'
        }

        $emitCloudPc = {
            param($raw)

            $isShared = ($raw.provisioningType -eq 'sharedByEntraGroup')

            if ($Type -eq 'Shared' -and -not $isShared) { return }
            if ($Type -eq 'Dedicated' -and $isShared) { return }

            $displayName = $raw.displayName
            $managedDeviceName = $raw.managedDeviceName
            $normalizedName = if ($displayName) { $displayName } else { $managedDeviceName }

            if ($Name) {
                $matchValues = @($normalizedName, $displayName, $managedDeviceName) |
                    Where-Object { -not [string]::IsNullOrWhiteSpace($_) } |
                    Select-Object -Unique

                $hasWildcard = [System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($Name)
                $isNameMatch = if ($hasWildcard) {
                    @($matchValues | Where-Object { $_ -like $Name }).Count -gt 0
                }
                else {
                    @($matchValues | Where-Object { $_ -eq $Name }).Count -gt 0
                }

                if (-not $isNameMatch) { return }
            }

            [pscustomobject]@{
                PSTypeName             = 'WindowsCloudPC.CloudPC'
                Id                     = $raw.id
                Name                   = $normalizedName
                DisplayName            = $displayName
                ManagedDeviceName      = $managedDeviceName
                ProvisioningType       = if ($isShared) { 'Shared' } else { 'Dedicated' }
                ProvisioningPolicyName = $raw.provisioningPolicyName
                ProvisioningPolicyId   = $raw.provisioningPolicyId
                ProvisioningStatus     = $raw.status
                ServicePlanName        = $raw.servicePlanName
                AssignedUserUpn        = if ($isShared) { $raw.sharedDeviceDetail.assignedToUserPrincipalName } else { $raw.userPrincipalName }
                ManagedDeviceId        = $raw.managedDeviceId
                AadDeviceId            = $raw.aadDeviceId
                LastModifiedDateTime   = if ($raw.lastModifiedDateTime) { ([datetime]$raw.lastModifiedDateTime).ToLocalTime() } else { $null }
                Raw                    = $raw
            }
        }

        if ($Id) {
            if ([string]::IsNullOrWhiteSpace($Id)) {
                throw "Get-CloudPC: Id cannot be empty."
            }

            $escapedId = [uri]::EscapeDataString($Id)
            $idUri = 'https://graph.microsoft.com/beta/deviceManagement/virtualEndpoint/cloudPCs/' +
                     $escapedId +
                     '?$select=' + [uri]::EscapeDataString($select)

            $raw = Invoke-MgGraphRequest -Method GET -Uri $idUri -Headers $headers
            & $emitCloudPc $raw
            return
        }

        Invoke-GraphPaged -Uri $uri -Headers $headers | ForEach-Object {
            & $emitCloudPc $_
        }
    }

    end { }
}