How to Check Active/Idle User Sessions in Windows Server 2012 Using Native PowerShell


2 views

When running query session or basic PowerShell commands like Get-WmiObject -Class Win32_LoggedOnUser, you get limited information - mainly usernames and session start times. What's missing is crucial session state data (active/idle/disconnected) that's essential for server administration.

Here's an enhanced PowerShell script that retrieves comprehensive session information without remote execution or third-party tools:


function Get-UserSessions {
    $sessions = query session | Where-Object { $_ -notmatch '^ SESSIONNAME' } | ForEach-Object {
        $session = $_.Trim() -split '\s+'
        [PSCustomObject]@{
            Username = $session[1]
            SessionID = $session[2]
            State = $session[3]
            SessionType = $session[0]
            ConnectedTime = if ($session.Count -gt 4) { $session[4..($session.Count-1)] -join ' ' } else { $null }
        }
    }

    # Get idle times using Win32_SessionProcess
    $idleTimes = Get-WmiObject -Class Win32_SessionProcess | ForEach-Object {
        $process = Get-WmiObject -Class Win32_Process -Filter "ProcessId = '$($_.ProcessId)'"
        [PSCustomObject]@{
            SessionID = $process.SessionId
            IdleTime = (Get-Date) - $process.ConvertToDateTime($process.CreationDate)
        }
    }

    # Combine data
    foreach ($session in $sessions) {
        $idleData = $idleTimes | Where-Object { $_.SessionID -eq $session.SessionID }
        $session | Add-Member -NotePropertyName IdleMinutes -NotePropertyValue ($idleData.IdleTime.TotalMinutes)
    }

    return $sessions
}

Get-UserSessions | Format-Table -AutoSize

The script returns these key indicators:

  • State: 'Active', 'Disc' (disconnected), or 'Listen'
  • IdleMinutes: Minutes since last input (calculated from process creation time)
  • SessionType: Console (local) or RDP-Tcp (remote)

To find only active non-idle sessions:


Get-UserSessions | Where-Object { $_.State -eq 'Active' -and $_.IdleMinutes -lt 5 }

To find disconnected sessions older than 1 hour:


Get-UserSessions | Where-Object { $_.State -eq 'Disc' -and $_.IdleMinutes -gt 60 }

The WMI queries add some overhead. For frequent monitoring, consider caching the idle time data or running it as a scheduled task that saves results to a log file.


While PowerShell's query user or Get-WmiObject Win32_LoggedOnUser provides basic logged-in user data, administrators often need deeper session state visibility. The native tools show session start times but lack critical details about whether sessions are active, disconnected, or idle.

Here are three built-in approaches with increasing levels of detail:

1. Enhanced PowerShell Query

# This provides more session state details than basic WMI queries
$sessions = qwinsta
$sessions | ForEach-Object {
    if ($_ -match "(\d+)\s+(\w+)\s+(\w+)\s+(\w+)\s+([\w\s]+)") {
        [PSCustomObject]@{
            SessionID = $matches[1]
            UserName = $matches[2]
            SessionState = $matches[4]
            IdleTime = $matches[5]
        }
    }
}

2. Using Terminal Services (RDS) Commands

# More detailed than PowerShell alone
query session /server:$env:COMPUTERNAME

3. Comprehensive Native Tool Combination

Combine multiple native commands for a complete picture:

# Get detailed session information
$output = cmd /c query user /server:$env:COMPUTERNAME
$sessions = $output | Select-Object -Skip 1 | ForEach-Object {
    $parts = $_ -split '\s+'
    [PSCustomObject]@{
        Username = $parts[1]
        SessionName = $parts[2]
        ID = $parts[3]
        State = $parts[4]
        IdleTime = $parts[5]
        LogonTime = $parts[6..($parts.Length-1)] -join ' '
    }
}
$sessions | Format-Table -AutoSize

Key status indicators in the output:

  • Active: Currently in use
  • Disc: Disconnected session
  • Idle: No input for period shown
  • .: Session not initialized

For continuous monitoring, create a PowerShell scheduled task:

# Session monitoring script
while ($true) {
    Clear-Host
    query user /server:$env:COMPUTERNAME
    Start-Sleep -Seconds 10
}

Once you've identified idle/disconnected sessions, manage them natively:

# Log off a specific session
logoff <sessionID> /server:$env:COMPUTERNAME

# Reset a disconnected session
tscon <sessionID> /dest:console