List RDP Sessions on Remote Servers in PowerShell

By | 2016-02-17

You can use this handy little script to find remote desktop sessions on all servers running in your Active Directory domain.

It’s a fact of life as a sysadmin.  You RDP to a machine, leave a task running, and disconnect. Invariably, you forget that session, and it sits their disconnected. Being a good admin, there is a password policy that requires you to change your password every 90 days.  The time comes, and you change your password, as required.

Bam. Your account is locked out. Now you get to go find all those abandoned sessions, running under your old credentials.  Good times.  Wouldn’t it be handy if you could simply run a script to find all your dead sessions?

We’ve all used the query session command to get a list of sessions on a remote server, then use the logoff command to remotely log off any dead sessions.  If you haven’t you can read up on it here: Killing Disconnected Terminal Server Sessions from the Command Line.

The general flow of the script is thus:

  • Import the Active Directory module (required), and set some variables.
  • Get a list of servers from Active Directory. I’ve included three methods of getting a list of machines in the script (two from AD, one from a file) within the script.
  • Iterate through the list with a ForEach loop, running qwinsta.exe against each host. This produces the same output as the query session command.
  • Parse the output of the qwinsta command.  In this script, the data seems to change places (my opinion, anyway), hence the hodgepodge of logical ANDs and whatnot.
  • Present the output to the user.

I’ve pasted the script below, and I hope someone gets some use out of this. As always, if you have any questions, comments, or concerns regarding this, drop a note in the comments, or start a thread in the forums. It’d be super cool if someone could improve upon this!

#
# import the active directory module
#

import-module activedirectory

#
# set some variables
#

$Today=Get-Date
$SessionList="`n`nRDP Session List - " + $Today + "`n`n"
$CurrentSN=0

#
# Get a list of servers from Active Directory. Note that two different strings have been
# given. The first one will get all servers in Active Directory, while the second one
# (which is commented) will target all hosts in a particular OU.  The third option is
# for grabbing a list of machines (one per line) from a file.
#

write-progress -activity "Getting list of servers from Active Directory" -status "... please wait ..."

$Servers=get-adcomputer -filter {OperatingSystem -like "*server*"}
# $Servers=Get-adcomputer -filter * -searchbase "OU=servers,dc=dwlab02,dc=local"
# $Servers=Get-Content "c:\files\myfile.txt"

$NumberOfServers=$Servers.Count

#
# Iterate through the retrieved list to check RDP sessions on each machine
#

ForEach ($Server in $Servers) {

    $ServerName=$Server.Name
    Write-progress -activity "Checking RDP Sessions" -status "Querying $ServerName" -percentcomplete (($CurrentSN/$NumberOfServers)*100)

    #
    # Run qwinsta and grab the output
    #

    try
    {
        $queryResults = (qwinsta /server:$ServerName | foreach { (($_.trim() -replace "\s+",","))} | convertfrom-csv)

        #
        # get session info from the instance
        #

        ForEach($QueryResult in $QueryResults) {
            
            $RDPUser=$QueryResult.USERNAME
            $SessionType=$QueryResult.SESSIONNAME
            $SessionID=$QueryResult.ID
            $ReturnedCurrentState=$QueryResult.State

            If($ReturnedCurrentState -eq $null){ $CurrentState="Disconnected" } Else { $CurrentState="Active" }
            
            #
            # filter out the chaff
            #

            If (($RDPUser -ne $NULL) -and ($SessionType -ne "console") -and ($SessionType -ne "services") -and ($SessionType -ne "rdp-tcp") -and ($RDPUser -ne "65536")) {
                $SessionList=$SessionList + "`n" + $ServerName + " logged in by " + $RDPUser + " on " + $SessionType + ", session id $SessionID $CurrentState"
            }
        }

    }
    catch
    {
        $SessionList=$SessionList + "`n Unable to query " + $ServerName
        write-host "Unable to query $ServerName!" -foregroundcolor Red
    }
    
    $CurrentSN++
}


# Send the output the screen.


$SessionList + "`n`n"

Author: dwirch

Derek Wirch is a seasoned IT professional with an impressive career dating back to 1986. He brings a wealth of knowledge and hands-on experience that is invaluable to those embarking on their journey in the tech industry.

Leave a Reply

Your email address will not be published. Required fields are marked *

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