Functions/Troubleshooting/Measure-Session.ps1
<#
.SYNOPSIS Get all sessions on the local system. .DESCRIPTION Use the qwinsta.exe command to retrieve all local sessions. .EXAMPLE PS C:\> session Use the alias of Measure-Session to show the local sessions. #> function Measure-Session { [CmdletBinding()] [Alias('session')] param ( # Flag to continue showing the memory every second. [Parameter(Mandatory = $false)] [ValidateSet('qwinsta', 'process')] [System.String] $Mode = 'qwinsta' ) $timestamp = Get-Date if ($Mode -eq 'qwinsta') { $rawSessions = qwinsta.exe $rawSessions = $rawSessions | Select-Object -Skip 1 $processesBySessionId = Get-Process | Group-Object -Property 'SessionId' -AsHashTable foreach ($rawSession in $rawSessions) { if ($rawSession.PadRight(68) -match '^(?<Active>.{1})(?<Name>.{18})(?<User>.{22})(?<Id>.{5}) (?<Status>.{8})(?<Type>.{12})(?<Device>.*)$') { $counterSession = [PSCustomObject] @{ PSTypeName = 'ProfileFever.Performance.Session' Timestamp = $timestamp Name = $Matches.Name.Trim() Id = $Matches.Id.Trim() -as [System.Int32] User = $Matches.User.Trim() Active = -not [System.String]::IsNullOrWhiteSpace($Matches.Active) Status = $Matches.Status.Trim() Type = $Matches.Type.Trim() Device = $Matches.Device.Trim() Processes = 0 Memory = 0 } # The process statistic per session. if ($processesBySessionId.ContainsKey($counterSession.Id)) { $processMeasure = $processesBySessionId[$counterSession.Id] | Measure-Object -Sum 'WorkingSet64' $counterSession.Processes = $processMeasure.Count $counterSession.Memory = $processMeasure.Sum } # Get the connection state. # https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ne-wtsapi32-wts_connectstate_class?redirectedfrom=MSDN switch ($counterSession.Status) { 'Aktiv' { $counterSession.Status = 'Active' } 'Active' { $counterSession.Status = 'Active' } 'Verb.' { $counterSession.Status = 'Connected' } # '' { $counterSession.Status = 'Connected' } # '' { $counterSession.Status = 'ConnectQuery' } # '' { $counterSession.Status = 'ConnectQuery' } # '' { $counterSession.Status = 'Shadow' } # '' { $counterSession.Status = 'Shadow' } 'Getr.' { $counterSession.Status = 'Disconnected' } 'Disc' { $counterSession.Status = 'Disconnected' } # '' { $counterSession.Status = 'Idle' } # '' { $counterSession.Status = 'Idle' } 'Abh”r.' { $counterSession.Status = 'Listen' } 'Listen' { $counterSession.Status = 'Listen' } # '' { $counterSession.Status = 'Reset' } # '' { $counterSession.Status = 'Reset' } # '' { $counterSession.Status = 'Down' } 'Down' { $counterSession.Status = 'Down' } # '' { $counterSession.Status = 'Init' } # '' { $counterSession.Status = 'Init' } } Write-Output $counterSession } } } if ($Mode -eq 'process') { $cimSessions = Get-CimInstance -ClassName 'Win32_Process' | Group-Object -Property 'SessionId' -AsHashTable $sessionIds = $cimSessions.Keys | Sort-Object foreach ($sessionId in $sessionIds) { $cimSessionProcesses = $cimSessions[$sessionId] $counterSession = [PSCustomObject] @{ PSTypeName = 'ProfileFever.Performance.Session' Timestamp = $timestamp Name = '' Id = $sessionId -as [System.Int32] User = $cimSessionProcesses | Where-Object { $_.Name -notin 'csrss.exe', 'winlogon.exe', 'dwm.exe' -and $_.Path -notlike '*\Citrix\*' } | Select-Object -First 1 | Invoke-CimMethod -MethodName 'GetOwner' | Select-Object -ExpandProperty 'User' Active = $cimSessionProcesses.ProcessId -contains $PID Status = '' Type = '' Device = '' Processes = $cimSessionProcesses.Count Memory = ($cimSessionProcesses | Measure-Object -Sum 'WorkingSetSize').Sum } Write-Output $counterSession } } } |