Public/Get-CloudPCUsage.ps1

function Get-CloudPCUsage {
    <#
    .SYNOPSIS
        Reports who is signed in to each Cloud PC and whether it is in use or available.

    .DESCRIPTION
        Uses the Cloud PC endpoint's connectivityResult.status for shared Cloud
        PCs because that signal updates almost immediately for shared devices.
        It still reads getCloudPcConnectivityHistory for last sign-in timestamps.
        Dedicated Cloud PCs use the beta getRealTimeRemoteConnectionStatus report
        endpoint for current sign-in status, then fall back to
        getCloudPcConnectivityHistory when the real-time report is unavailable.
        The result is enriched with the current user from the
        matching Intune managedDevice (dedicated) or sharedDeviceDetail (shared).

        UsageStatus values:
            inUse A shared endpoint or dedicated connectivity event says a user is signed in
            available Reachable, nobody signed in or assigned
            unavailable The Cloud PC service marks the PC as unreachable
            failed Last connectivity check failed
            unknown Neither signal returned anything (rare — usually means a brand
                          new PC whose first telemetry hasn't landed yet)

        Source of truth by provisioning type:
            Shared cloudPC.connectivityResult.status from the Cloud PC endpoint.
                        Connectivity history enriches LastActiveTime only.
            Dedicated getRealTimeRemoteConnectionStatus, then
                        getCloudPcConnectivityHistory, then
                        cloudPC.connectivityResult.status.

        CurrentUser* fields are populated independently of UsageStatus:
            Shared From sharedDeviceDetail.assignedToUserPrincipalName.
            Dedicated From the managedDevice's most recent usersLoggedOn entry, falling
                        back to userPrincipalName / userDisplayName on the device.

    .PARAMETER CloudPC
        Pipe in WindowsCloudPC.CloudPC objects from Get-CloudPC, or pass one or
        more Cloud PC IDs or names. String values are resolved against Get-CloudPC
        using exact matches on Id, Name, managedDeviceName, or displayName.

    .PARAMETER ProvisioningPolicyId
        Limit the report to a single provisioning policy.

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

    .EXAMPLE
        Get-CloudPCUsage | Format-Table CloudPcName,UsageStatus,CurrentUserDisplayName,LastActiveTime

    .EXAMPLE
        # Only Cloud PCs with an active session
        Get-CloudPCUsage | Where-Object UsageStatus -eq 'inUse'

    .EXAMPLE
        # Find idle dedicated PCs (reclamation candidates)
        Get-CloudPCUsage -Type Dedicated | Where-Object DaysSinceLastSignIn -ge 30

    .EXAMPLE
        # Pre-filter then enrich
        Get-CloudPC -Type Dedicated | Get-CloudPCUsage

    .EXAMPLE
        # Resolve one Cloud PC by ID or name
        Get-CloudPCUsage -CloudPC '<cloud-pc-id-or-name>'
    #>

    [CmdletBinding()]
    [OutputType('WindowsCloudPC.CloudPCUsage')]
    param(
        [Parameter(ValueFromPipeline)]
        [object[]]$CloudPC,

        [string]$ProvisioningPolicyId,

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

    begin {
        Connect-CloudPC | Out-Null
        $bag   = New-Object System.Collections.Generic.List[object]
        $piped = $false
    }

    process {
        if ($CloudPC) {
            $piped = $true
            foreach ($pc in $CloudPC) { $bag.Add($pc) }
        }
    }

    end {
        if (-not $piped) {
            $bag = [System.Collections.Generic.List[object]]@(
                Get-CloudPC -ProvisioningPolicyId $ProvisioningPolicyId -Type $Type
            )
        }

        $resolvedBag = New-Object System.Collections.Generic.List[object]
        $cloudPcLookup = $null
        foreach ($item in $bag) {
            if ($null -eq $item) {
                throw "CloudPC cannot be null, empty, or whitespace."
            }

            if ($item.PSObject.TypeNames -contains 'WindowsCloudPC.CloudPC') {
                $resolvedBag.Add($item)
                continue
            }

            if ($item -is [string]) {
                if ([string]::IsNullOrWhiteSpace($item)) {
                    throw "CloudPC cannot be null, empty, or whitespace."
                }

                if (-not $cloudPcLookup) {
                    $cloudPcLookup = @(Get-CloudPC -ProvisioningPolicyId $ProvisioningPolicyId -Type $Type)
                }

                $matches = @(
                    $cloudPcLookup | Where-Object {
                        $_.Id -eq $item -or
                        $_.Name -eq $item -or
                        $_.ManagedDeviceId -eq $item -or
                        $_.Raw.managedDeviceName -eq $item -or
                        $_.Raw.displayName -eq $item
                    }
                )

                if ($matches.Count -eq 0) {
                    throw "Could not find a Cloud PC matching '$item'. Pass a Cloud PC object from Get-CloudPC, or use an exact Cloud PC ID or name."
                }
                if ($matches.Count -gt 1) {
                    throw "Cloud PC identifier '$item' matched multiple Cloud PCs. Pass a Cloud PC object from Get-CloudPC or use a unique Cloud PC ID."
                }

                $resolvedBag.Add($matches[0])
                continue
            }

            throw "CloudPC must be a WindowsCloudPC.CloudPC object from Get-CloudPC, or a Cloud PC ID or name string."
        }
        $bag = $resolvedBag

        foreach ($pc in $bag) {
            # ---- UsageStatus ------------------------------------------------
            $connStatus = $pc.Raw.connectivityResult.status
            $isShared = $pc.ProvisioningType -eq 'Shared'
            $signInStatus        = $null
            $daysSinceLastSignIn = $null
            $lastActiveTime      = $null

            $realTimeStatus = if (-not $isShared -and $pc.Id) { Get-CloudPCRealTimeStatus -CloudPcId $pc.Id } else { $null }
            $history = @()
            $userEvents = @()
            $latestStart = $null

            if ($isShared -or -not $realTimeStatus) {
                $history = @(if ($pc.Id) { Get-CloudPCConnectivityHistory -CloudPcId $pc.Id })
                $userEvents = @(
                    $history |
                        Where-Object EventType -eq 'userConnection' |
                        Sort-Object EventDateTime -Descending
                )
                $latestStart = $userEvents |
                    Where-Object { $_.EventName -eq 'Connection Started' -and $_.EventResult -eq 'success' } |
                    Select-Object -First 1

                if ($latestStart) {
                    $lastActiveTime = $latestStart.EventDateTime
                    $daysSinceLastSignIn = [math]::Max(
                        0,
                        [int][math]::Floor((New-TimeSpan -Start $latestStart.EventDateTime -End (Get-Date)).TotalDays)
                    )
                }
            }

            if ($isShared) {
                $usageStatus = if ($connStatus) { $connStatus } else { 'unknown' }
                $signInStatus = switch ($connStatus) {
                    'inUse'     { 'SignedIn' }
                    'available' { 'NotSignedIn' }
                    default     { $null }
                }
            }
            else {
                if ($realTimeStatus) {
                    $signInStatus = $realTimeStatus.SignInStatus
                    $daysSinceLastSignIn = $realTimeStatus.DaysSinceLastSignIn
                    $lastActiveTime = $realTimeStatus.LastActiveTime
                    $usageStatus = switch ($realTimeStatus.SignInStatus) {
                        'SignedIn'    { 'inUse' }
                        'NotSignedIn' { 'available' }
                        default       { if ($connStatus) { $connStatus } else { 'unknown' } }
                    }
                }
                elseif ($latestStart) {
                    $terminalEvent = $userEvents |
                        Where-Object {
                            $_.ActivityId -eq $latestStart.ActivityId -and
                            $_.EventDateTime -gt $latestStart.EventDateTime -and
                            ($_.EventName -eq 'Connection Finished' -or $_.EventResult -eq 'failure')
                        } |
                        Select-Object -First 1

                    if (-not $terminalEvent) {
                        $signInStatus = 'SignedIn'
                        $usageStatus = 'inUse'
                    }
                    else {
                        $signInStatus = 'NotSignedIn'
                        $usageStatus = 'available'
                    }
                }
                elseif ($userEvents) {
                    $signInStatus = 'NotSignedIn'
                    $usageStatus = 'available'
                }
                else {
                    $usageStatus = if ($connStatus) { $connStatus } else { 'unknown' }
                    $signInStatus = switch ($connStatus) {
                        'inUse'     { 'SignedIn' }
                        'available' { 'NotSignedIn' }
                        default     { $null }
                    }
                }
            }

            # ---- CurrentUser* enrichment ------------------------------------
            $currentUserUpn  = $null
            $currentUserName = $null
            $currentUserId   = $null
            $sessionStart    = $null

            if ($pc.ProvisioningType -eq 'Shared') {
                $currentUserUpn = $pc.AssignedUserUpn
                $rawSessionStart = $pc.Raw.sharedDeviceDetail.sessionStartDateTime
                if ($rawSessionStart) {
                    try { $sessionStart = ([datetime]$rawSessionStart).ToLocalTime() } catch { $sessionStart = $null }
                }
                if ($currentUserUpn) {
                    $u = Resolve-CloudPCUser -IdOrUpn $currentUserUpn
                    $currentUserName = $u.DisplayName
                    $currentUserId   = $u.Id
                }
            }
            else {
                $md = if ($pc.ManagedDeviceId) { Get-CloudPCManagedDevice -ManagedDeviceId $pc.ManagedDeviceId } else { $null }
                if ($md) {
                    $logon = $md.usersLoggedOn |
                        Sort-Object { [datetime]$_.lastLogOnDateTime } -Descending |
                        Select-Object -First 1
                    if ($logon) {
                        $u = Resolve-CloudPCUser -IdOrUpn $logon.userId
                        $currentUserUpn  = $u.Upn
                        $currentUserName = $u.DisplayName
                        $currentUserId   = $u.Id
                        $sessionStart    = ([datetime]$logon.lastLogOnDateTime).ToLocalTime()
                    }
                    else {
                        $currentUserUpn  = $md.userPrincipalName
                        $currentUserName = $md.userDisplayName
                    }
                }
                else {
                    $currentUserUpn = $pc.AssignedUserUpn
                }
            }

            [pscustomobject]@{
                PSTypeName             = 'WindowsCloudPC.CloudPCUsage'
                CloudPcName            = $pc.Name
                ProvisioningType       = $pc.ProvisioningType
                ProvisioningPolicyName = $pc.ProvisioningPolicyName
                ProvisioningStatus     = $pc.ProvisioningStatus
                UsageStatus            = $usageStatus
                SignInStatus           = $signInStatus
                DaysSinceLastSignIn    = $daysSinceLastSignIn
                LastActiveTime         = $lastActiveTime
                AssignedUserUpn        = $pc.AssignedUserUpn
                CurrentUserUpn         = $currentUserUpn
                CurrentUserDisplayName = $currentUserName
                CurrentUserId          = $currentUserId
                SessionStart           = $sessionStart
                CloudPcId              = $pc.Id
                ManagedDeviceId        = $pc.ManagedDeviceId
            }
        }
    }
}