Force a user logoff remotely with PowerShell

Send Us a Sign! (Contact Us!)

There are a number of reasons to do this, including employee termination, as a troubleshooting measure or simply to free up some sessions on a remote desktop server. Knowing how to do this from the command line will prevent either having to yell at users over the phone to log off, or having to access their remote consoles via VNC. Using the command line also gives an admin the opportunity to perform this task across many machines or users at once, if necessary.

The first way is by using the logoff command. This command has been around a long time. Many admins are not aware of this command, let alone that it has the ability to perform remote logoffs!

The logoff utility can log off users remotely but requires an extra step of finding a session ID. So first, we must find this ID. We can do this by using the quser utility and the server argument as you can see below:

Force a user logoff remotely with PowerShell

Notice the value of 2 under the ID field. That is the session ID we need. However, unfortunately, since quser is not a PowerShell command that would return a structured object, we will have to parse this string to pull out that value. To pull out this value by itself, we can use the Where-Object command and do a little regular expression matching to make it happen.

$userName = 'administrator'
$sessionId = ((quser /server:DC | Where-Object { $_ -match $userName }) -split ' +')[2]
$sessionId

Above, we are searching for any user with the name of administrator and only returning the session ID. Once we have the session ID, we can now use this ID with the logoff command to log off the administrator account remotely on the DC computer.

logoff $sessionId /server:DC

Another method is to use WMI/CIM and the Win32Shutdown() method. This method doesn't force you to find a user session first but also doesn't give you the ability to pick a user either. This method will just log off all users interactively logged on to the remote computer. You can do this on a single line in PowerShell.

Below, you can see that we are invoking a CIM method on the DC computer again and specifying 4 as a flag. This forcefully logs off the user. You can use 0 here too to perform a "graceful" logoff.

Invoke-CimMethod -ClassName Win32_Operatingsystem -ComputerName DC -MethodName Win32Shutdown -Arguments @{ Flags = 4 }

There's one last method if the client system from which you're invoking the command is Windows 10. In this case, you should have the Invoke-RDUserLogoff command available to you. Using this method is similar to using the logoff utility. You must first obtain the session ID using quser or the qwinsta utility if the remote server is not running Remote Desktop Services.

$userName = 'administrator'
$sessionId = ((quser /server:DC | Where-Object { $_ -match $userName }) -split ' +')[2]

After acquiring the session ID, you can pass it to Invoke-RDUserLogoff with the UnifiedSessionId parameter and use the HostServer parameter to pass along the remote computer name.

Invoke-RDUserLogoff -HostServer DC -UnifiedSessionId $sessionId

By now, we hope you've seen enough ways to log off a user from a remote computer. Each method performs the task in a different way but in the end gets the same job done.

A useful script

The following script is a useful piece of code in Powershell, that use the logoff utility as core, to log a single or multiple users on a single system:

cls
Write-Host '******************************'
Write-Host '* Log Off User Remotely *'
Write-Host '******************************'
Write-Host

$global:adminCreds = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password.", "", "")
$global:ComputerName = Read-Host 'Computer Name?'
Function getSessions {
Write-host
Write-host "Getting user sessions..."
Write-Host
Write-Host '***************************************************************************'
Invoke-Command -ComputerName $global:ComputerName -scriptBlock {query session} -credential $global:adminCreds
}

Function logUserOff {
Write-Host
$SessionNum = Read-Host 'Session ID number to log off?'
$title = "Log Off"
$message = "Are you sure you want to log them off?"
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Logs selected user off."
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Exits."
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result = $host.ui.PromptForChoice($title, $message, $options, 1)

switch ($result){
0 {
Write-Host
Write-Host 'OK. Logging them off...'
Invoke-Command -ComputerName $global:ComputerName -scriptBlock {logoff $args[0]} -ArgumentList $SessionNum -credential $global:adminCreds
Write-Host
Write-Host 'Success!' -ForegroundColor green
break
}
1 {break}
}
}

Do {
getSessions
logUserOff

Write-Host
#Write-Host "Press any key to continue ..."
# $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

#Configure yes choice
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Remove another profile."

#Configure no choice
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No","Quit profile removal"

#Determine Values for Choice
$choice = [System.Management.Automation.Host.ChoiceDescription[]] @($yes,$no)

#Determine Default Selection
[int]$default = 0

#Present choice option to user
$userchoice = $host.ui.PromptforChoice("","Logoff Another Profile?",$choice,$default)
}
#If user selects No, then quit the script
Until ($userchoice -eq 1)