Get a list of users logged on a list of servers – Powershell

Get a list of users logged on a list of servers – Powershell

This post will show you how to get a list of users logged on a list of servers (or a specific server) and how to format the output in order to work with it, in Powershell.

Specifically, we will leverage quser, let’s see a quick example on how to query the current user sessions on a remote server.

quser /server:myserver.itdroplets.com

The above command, will look like this.

quser_simple-example

This is just text however. If we were to assign that result into a variable (with Invoke-Command for instance), it’ll still be unmanageable. We can work with -Replace and with ConvertFrom-Csv in order to get this output to look decent.

Just for the sake of showing every step, the code below will first grab the list of sessions on a remote server and then use the -Replace and the ConvertFrom-Csv.

$Server = "myserver.itdroplets.com"

#Get all sessions, without working on the output
$Sessions = quser /server:$Server

#Sort the Output (and keep the same variable name)
$Sessions = $Sessions -replace  '\s{2,}', ',' | ConvertFrom-Csv

We’re not out of the woods yet, but here’s how the output looks like now.quser_output-converted-from-csv-after-replace

I’ve added some color to show you what the problem is at the minute. The output in green is good and it’ll always be good as long as the session is Active. The ones in yellow though have their values shifted up. That’s because SESSIONNAME doesn’t exist and so converting it to CSV shifted all values up.

To fix this, we just need the script to identify all sessions where SESSIONNAME isn’t like “console” and not like “rdp-tcp*“. When this is the case (like in the yellow sessions in the screenshot above), then we need to shift the values and we’re done! So, SESSIONNAME will have to be empty, the ID will match SESSIONNAME, the STATE will match the ID and so on.

$Server = "myserver.itdroplets.com"

#Initialize $Sessions which will contain all sessions
[System.Collections.ArrayList]$Sessions = New-Object System.Collections.ArrayList($null)

#Get the current sessions on $Server and also format the output
$DirtyOuput = (quser /server:$Server) -replace '\s{2,}', ',' | ConvertFrom-Csv
 
#Go through each session in $DirtyOuput
Foreach ($session in $DirtyOuput) {
  #Initialize a temporary hash where we will store the data
  $tmpHash = @{}
  
  #Check if SESSIONNAME isn't like "console" and isn't like "rdp-tcp*"
  If (($session.sessionname -notlike "console") -AND ($session.sessionname -notlike "rdp-tcp*")) {
    #If the script is in here, the values are shifted and we need to match them correctly
    $tmpHash = @{
	  Username = $session.USERNAME
      SessionName = "" #Session name is empty in this case
      ID = $session.SESSIONNAME
      State = $session.ID
      IdleTime = $session.STATE
      LogonTime = $session."IDLE TIME"
	  Server = $Server
	}
	}Else  {
	  #If the script is in here, it means that the values are correct
	  $tmpHash = @{
	  Username = $session.USERNAME
	  SessionName = $session.SESSIONNAME
	  ID = $session.ID
	  State = $session.STATE
	  IdleTime = $session."IDLE TIME"
	  LogonTime = $session."LOGON TIME"
	  Server = $Server
	  }
	}
	#Add the hash to $Sessions
	$Sessions.Add((New-Object PSObject -Property $tmpHash)) | Out-Null
  }

#Display the sessions and just show Username, ID and Server
$sessions | select Username, ID, $Server | FT

The full Script that will handle multiple Servers

$Servers = @(
  "myserver1.itdroplets.com"
  "myserver2.itdroplets.com"
)

#Initialize $Sessions which will contain all sessions
[System.Collections.ArrayList]$Sessions = New-Object System.Collections.ArrayList($null)

#Go through each server
Foreach ($Server in $Servers)  {
	#Get the current sessions on $Server and also format the output
	$DirtyOuput = (quser /server:$Server) -replace '\s{2,}', ',' | ConvertFrom-Csv
	
	#Go through each session in $DirtyOuput
	Foreach ($session in $DirtyOuput) {
	#Initialize a temporary hash where we will store the data
	$tmpHash = @{}
	
	#Check if SESSIONNAME isn't like "console" and isn't like "rdp-tcp*"
	If (($session.sessionname -notlike "console") -AND ($session.sessionname -notlike "rdp-tcp*")) {
		#If the script is in here, the values are shifted and we need to match them correctly
		$tmpHash = @{
		Username = $session.USERNAME
		SessionName = "" #Session name is empty in this case
		ID = $session.SESSIONNAME
		State = $session.ID
		IdleTime = $session.STATE
		LogonTime = $session."IDLE TIME"
		ServerName = $Server
		}
		}Else  {
		#If the script is in here, it means that the values are correct
		$tmpHash = @{
		Username = $session.USERNAME
		SessionName = $session.SESSIONNAME
		ID = $session.ID
		State = $session.STATE
		IdleTime = $session."IDLE TIME"
		LogonTime = $session."LOGON TIME"
		ServerName = $Server
		}
		}
		#Add the hash to $Sessions
		$Sessions.Add((New-Object PSObject -Property $tmpHash)) | Out-Null
	}
}
  
#Display the sessions, sort by name, and just show Username, ID and Server
$sessions | Sort Username | select Username, ID, ServerName | FT

Here’s the output.

Get-list-of-users-logged-on-a-list-of-servers_Powershell

That’s it on how to get a list of users logged on a list of servers.

IT Droplets

IT Droplets