Public/Get-WorkloadSessionStatus.ps1

function Get-WorkloadSessionStatus {
    <#
    .SYNOPSIS
        Returns the current state of all WorkloadsSessionHost processes.

    .DESCRIPTION
        Enumerates every running WorkloadsSessionHost.exe instance and returns
        a structured report including PID, memory usage, CPU time, start time,
        and process age. Also includes an aggregate summary.

        Designed for RMM dashboards, ad-hoc diagnostics, and pipeline filtering
        to identify high-memory instances.

    .EXAMPLE
        Get-WorkloadSessionStatus

        Returns all WorkloadsSessionHost instances with metrics.

    .EXAMPLE
        Get-WorkloadSessionStatus | Where-Object MemoryMB -gt 500

        Filter to processes exceeding 500MB.

    .EXAMPLE
        Get-WorkloadSessionStatus | Format-Table -AutoSize

        Display a formatted table of all instances.

    .OUTPUTS
        PSCustomObject[]
        Each object contains: PID, ProcessName, MemoryMB, CpuSeconds,
        StartTime, AgeSeconds, and Status properties.

    .LINK
        https://github.com/DailenG/WinslopFix
    #>

    [CmdletBinding()]
    [OutputType([PSCustomObject[]])]
    param(
        [Parameter()]
        [string]$ProcessName = 'WorkloadsSessionHost'
    )

    process {
        $now       = Get-Date
        $processes = @(Get-WinslopFixProcess -ProcessName $ProcessName -ErrorAction SilentlyContinue)

        if ($processes.Count -eq 0) {
            Write-Verbose "No '$ProcessName' processes found."
            return [PSCustomObject]@{
                Status              = 'NoProcessesFound'
                ProcessName         = $ProcessName
                InstanceCount       = 0
                TotalMemoryMB       = 0
                Timestamp           = $now.ToString('o')
            }
        }

        $results = [System.Collections.Generic.List[PSCustomObject]]::new()

        foreach ($proc in $processes) {
            $memoryMB   = [math]::Round($proc.PrivateMemorySize64 / 1MB, 1)
            $cpuSeconds = [math]::Round($proc.TotalProcessorTime.TotalSeconds, 1)
            $startTime  = $proc.StartTime
            $ageSeconds = [math]::Round(($now - $startTime).TotalSeconds, 0)

            $results.Add([PSCustomObject]@{
                PSTypeName  = 'WinslopFix.SessionStatus'
                PID         = $proc.Id
                ProcessName = $proc.ProcessName
                MemoryMB    = $memoryMB
                CpuSeconds  = $cpuSeconds
                StartTime   = $startTime
                AgeSeconds  = $ageSeconds
                Status      = 'Running'
                Timestamp   = $now.ToString('o')
            })
        }

        # Append aggregate summary as the final object
        $totalMemory = ($results | Measure-Object -Property MemoryMB -Sum).Sum
        $results.Add([PSCustomObject]@{
            PSTypeName  = 'WinslopFix.SessionSummary'
            PID         = $null
            ProcessName = $ProcessName
            MemoryMB    = [math]::Round($totalMemory, 1)
            CpuSeconds  = [math]::Round(($results | Measure-Object -Property CpuSeconds -Sum).Sum, 1)
            StartTime   = $null
            AgeSeconds  = $null
            Status      = "Summary ($($processes.Count) instances)"
            Timestamp   = $now.ToString('o')
        })

        return $results
    }
}