Identify what servers a user is logged on to with powershell
I am guilty to disconnect from a server and forget all about it and perhaps, months later, I find myself logged on that server. I built a quick script that helps me with this every now and then. Or perhaps you’re onto somebody else 🙂 Let’s see how to identify what servers a user is logged on to with powershell!
First things first, you will need a list of servers (this will work on all clients as long as you have rights to query all of the machines).
I prefer to grab the list from Active Directory (you will need AD-RSAT tools with Powershell unless you run this on a Domain Controller) with the following command:
#The command will also exclude any disabled machine to avoid wasting time to try to reach them. $serverList=(Get-ADComputer -Filter ('(OperatingSystem -Like "*SERVER*") -AND (Enabled -Eq "True")') | select-object Name).Name
If you have already a simple list of hostnames stored in a text file, you can import it with:
$serverList = Get-Content "C:\Users\ItdropletsUser\desktop\servers.txt"
Let’s see the whole script, it’s commented so that you can understand, but I’ll go through it:
#The username to check against each server $Username = "user.name" #Output file $csvOutput = 'C:\whereisloggedon.csv' #Deletes the output file if it exists If (Test-Path $csvOutput){ Remove-Item $csvOutput } #Add the first line to the CSV file Add-Content -Path $csvOutput -Value "Hostname,SessionID" #Get all Servers' names in the Domain that are not enabled. $serverList=(Get-ADComputer -Filter ('(OperatingSystem -Like "*SERVER*") -AND (Enabled -Eq "True")') | select-object Name).Name #Start a foreach cycle which will go through each Server in the ServerList foreach ($Server in $serverList) { #Ping the Server $ping = Test-Connection $Server -Count 1 -EA Silentlycontinue #If Ping is successfull then keep going if($ping) { #Get server session ID if $username is logged on - cmd /c is needed for the 2>NUL to avoid quser to write "No User exists for *" when nobody is logged on a server. $sessionID = ((cmd /c quser /server:$server "2>NUL"| ? { $_ -match $username }) -split ' +')[2] #If sessionsID exists, write it to console and to the output file but exclude any live RDP connection or console (ie: rdp-tcp#1) If ($sessionID -AND $sessionID -NotLike "*rdp*" -AND $sessionID -ne "console") { #Write to console Write-Host "$($Username) is logged on $($Server) with ID: $($sessionID)" #Write into $csvOutput Add-Content -Path $csvOutput -Value "$($Server),$($sessionID)" } } }
So what’s happening is very simple:
- First I stated the username (just the username and not the domain etc).
- The csvOutput is the file that will be stored in C:\ which will contain a list of Hostames and Session IDs. In the script I also initialised it so that the first line will have Hostname,Session ID.
- I then grabbed the list of servers that are not disabled from Active Directory.
- In the foreach cycle, I went through each server in the Server List. For each server the script will:
- Try to ping it (with just one request to make it faster).
- Grab the session ID when the user matches. This is the most important line of the script. Also note that I used cmd /c so that I could use “2>NUL”. This is a nice workaround to avoid the script to output No User exists for *. This output is displayed every time quser hits a server with no users logged on to it.
- Check if the Session ID exists, it makes sure it doesn’t contain “rdp” and that does not contain “console”. In my opinion we should avoid to grab a list of active sessions, especially if you want to use the csv file at a later stage to kill these sessions. Perhaps you’re logged off and you’re going to kill an active session from another user, losing all of his/her work!
- If the Session ID respected the above criteria, then write to console something like User.Name is logged on SERVER01 with ID:5 and then it’ll also write SERVER01,5 in the CSV file.
That’s it! This is how you identify what servers a user is logged on to with powershell.
Note: Somebody might suggest a different approach which is grabbing all explorer.exe on the server and then check its owner in another cycle. I do not like this approach as you might be in an environment with servers running without a GUI!