August 27th, 2019

Automating Quser through PowerShell

Doctor Scripto
Scripter

Summary: Using PowerShell to automate Quser to identify users to Logoff systems in Windows

Hey Doctor Scripto! I need to log a user off every computer they’re logged into. The problem is, I don’t know which ones. How can I discover which computers they’re logged into and then log them off?

That’s a most excellent question!  I know just the person who can answer that.   I was talking my good friend Dan Reist on this topic.   Dan is a Senior Consultant on Data Platforms here at Microsoft.   He actually ran into that same issue.

Dan, the room is yours today, take it away!

Thanks Doctor Scripto!

So my first thought to that is “Very carefully!”  Let’s simplify the question by looking at one specific computer.

First, let’s define the username and computer name we’re investigating.

$userName = ‘randomnote1’
$computer = ‘sqlserver01’

Now, let’s use the quser (query user) command to get all the user sessions on the computer.

$quserResult = quser /server:$computer 2>&1

When we examine the contents of the $quserResult variable it contains a nicely formatted table

USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
randomnote1 console 1 Active none 8/14/2019 6:52 AM

Cool, we can clearly see that the user randomnote1 is logged onto this computer. The problem is, this is just a string array. Not very easy to work with! However, it looks like the table is formatted with at least two spaces between each column. That should be easy to replace with some commas to make a CSV!

$quserRegex = $quserResult | ForEach-Object -Process { $_ -replace '\s{2,}',',' }

Now when we look at the contents of $quserRegex, we can see an array of comma separated values.

USERNAME,SESSIONNAME,ID,STATE,IDLE TIME,LOGON TIME randomnote1,console,1,Active,none,8/14/2019 6:52 AM

Now we’re getting somewhere. Let’s use ConvertFrom-Csv to convert the CSV into a PowerShell object.

$quserObject = $quserRegex | ConvertFrom-Csv

Look at the contents of $quserObject, we can see it now looks like a PowerShell object!

USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME ————————————————————————– randomnote1 console 1 Active none 8/14/2019 6:52 AM

Finally, we can extract the session id for the user we need to log off and log the user off the computer!

$userSession = $quserObject | Where-Object -FilterScript { $_.USERNAME -eq 'randomnote1' }
logoff $userSession.ID /server:$computer

That’s all there is to it! Now you can operationalize it by performing these steps over an array of computers.

$computers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name
foreach ( $computer in $computers )
{
	$quserResult = quser /server:$computer 2>&1
	If ( $quserResult.Count -gt 0 )
{
		$quserRegex = $quserResult | ForEach-Object -Process { $_ -replace '\s{2,}',',' }
		$quserObject = $quserRegex | ConvertFrom-Csv
		$userSession = $quserObject | Where-Object -FilterScript { $_.USERNAME -eq 'randomnote1' }
		If ( $userSession )
		{
			logoff $userSession.ID /server:$computer
		}
	}
}

Thank you Dan!  That’s not only a cool trick but a beautiful example of using both legacy Console commands and PowerShell together to produce a new solution!

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Forum. See you tomorrow. Until then, peace.

Your good friend, Doctor Scripto

Doctor Scripto, Dan Reist, PowerShell

 

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

0 comments

Discussion are closed.