PowerShell: Finding user sessions on RDSH servers

If you’ve been working with Citrix Metaframe/Presentation Server/XenApp and/or Microsoft Terminal Server/Terminal Services/Remote Desktop Session Host for a while you’ll probably be familiar with the command line utility quser (or query user). It returns a tabular output showing details of users currently logged on:

 a-user                ica-tcp#15          1  Active          7  08/04/2014 07:19
 an-other              ica-tcp#16          2  Active          .  08/04/2014 08:26
 all-rest              ica-tcp#19          3  Active          .  08/04/2014 08:36
 no-play               ica-tcp#20          5  Active          .  08/04/2014 08:37
 b-usy                 ica-tcp#18          4  Active          .  08/04/2014 08:30

You can get the same information from a remote server by appending /server:<servername> onto the end of the command.

If no users are logged on to the server being queried then the command returns (via StdErr):

No User exists for *

This is a very useful command.Very untouched by Microsoft for approaching the last 15 years…

Which is a shame because the output format leaves a little to be desired. For example if there are some disconnected sessions the table format goes a bit awry:

 a-user                                 2  Disc        none   07/04/2014 09:58
 an-other           ica-tcp#69          1  Active          .  08/04/2014 08:15

Looks ok on screen but try and parse that empty SESSIONAME column from a scripting point of view, nasty.

So you can use this command to retrieve information, but for anything other than a basic test of “is somebody logged on or not” for scripting purposes it’s not ideal.

Oh, and there’s basically no (built in) PowerShell equivalent. You might be able to use Get-RDUserSession, or not, depending on whether your server is part of a Remote Desktop Deployment.

So, I tried using WMI to get a count of user sessions:

$OSVersion = (Get-WmiObject -Class Win32_OperatingSystem -ComputerName $NewVMName).Version
if($OSVersion -eq "5.2.3790"){
    # Server 2003
    $ActiveSessions = (Get-WmiObject -Class Win32_PerfRawData_TermService_TerminalServices -ComputerName $NewVMName).ActiveSessions
    $InactiveSessions = ((Get-WmiObject -Class Win32_PerfRawData_TermService_TerminalServices -ComputerName $NewVMName).InactiveSessions - 1) # subtract one for "Console" session
} else {
    $ActiveSessions = (Get-WmiObject -Class Win32_PerfRawData_LocalSessionManager_TerminalServices -ComputerName $NewVMName).ActiveSessions
    $InactiveSessions = ((Get-WmiObject -Class Win32_PerfRawData_LocalSessionManager_TerminalServices -ComputerName $NewVMName).InactiveSessions - 2) # subtract two for "Service" and "Console" sessions

Which as you can see, is a little fiddly due to the classes being different between 2003 and newer OSs, and that the console and service sessions are included. It also doesn’t tell you if there is a user logged on to the (local) console, as there is always a console session present. Not ideal if you’re wanting to ensure there are no people logged on to a server prior to rebooting/rebuilding it.

So in the end I’ve gone back to old faithful, quser:

$Server = "SomeServerName"
$ErrorActionPreference = "Continue"
$QUResult = quser /server:$Server 2>&1
$ErrorActionPreference = "Stop"
if($QUResult -notmatch "no user exists for"){
    Write-Host "Sessions found" -ForegroundColor Red

Note that I’m setting $ErrorActionPreference to “Continue” because I tend to set it to “Stop” at the top of my scripts (not shown in the chunk above) and because quser returns the “No User exists for *” text via StdErr, the script will stop with an error if there are no users logged on. That’s also the reason for the 2>&1 on the end of the quser command line – re send the StdErr output to the same place as StdOut, to ensure they both end up in the $QUResult variable irrespective of whether users are logged on or not.

This entry was posted in PowerShell, Remote Desktop, Scripting and tagged , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.