This site uses cookies to deliver our services and to show you relevant ads and job listings.
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and our Terms of Service.
Your use of Stack Overflow’s Products and Services, including the Stack Overflow Network, is subject to these policies and terms.

Join us in building a kind, collaborative learning community via our updated
Code of Conduct.

I am trying to formulate a Powershell command to remotely log off a user. We have a terminal server with a very unstable program that sometimes locks sessions. We have to remotely log off a user but I'm trying to write a Powershell statement that will log off the person who ran the script. I Googled around, and found this command:

Invoke-Command -ComputerName MyServer -Command {shutdown -l}

However, the command returns "incorrect function." I can run other commands successfully in the brackets, such as Get-Process.

The idea is for me to put that into a script that users can run to log themselves off of the server (since when it locks, they cannot access the start menu or ALT+CTRL+END to do it through the GUI).

The flow would be this:
Bob logs into MyServer via RDP but his session freezes. On his local desktop, he can run MyScript (containing a command similar to above) which will log off his session on MyServer.

9 Answers
9

C:\> logoff /?
Terminates a session.
LOGOFF [sessionname | sessionid] [/SERVER:servername] [/V] [/VM]
sessionname The name of the session.
sessionid The ID of the session.
/SERVER:servername Specifies the Remote Desktop server containing the user
session to log off (default is current).
/V Displays information about the actions performed.
/VM Logs off a session on server or within virtual machine.
The unique ID of the session needs to be specified.

The session ID can be determined with the qwinsta (query session) or quser (query user) commands (see here):

@jlacroix You may be able to work around this by mapping a local drive in the RDP session and run quser | find "%USERNAME%" >D:\path\to\session.txt in a logon script on the terminal server (replace D:\path\to\session.txt with the path to the output file on the mapped drive). That way a script on the client can read the session ID from a local file.
– Ansgar WiechersAug 19 '13 at 15:04

Here's a great scripted solution for logging people out remotely or locally. I'm using qwinsta to get session information and building an array out of the given output. This makes it really easy to iterate through each entry and log out only the actual users, and not the system or RDP listener itself which usually just throws an access denied error anyway.

In the first line of this script give $serverName the appropriate value or localhost if running locally. I use this script to kick users before an automated process attempts to move some folders around. Prevents "file in use" errors for me. Another note, this script will have to be ran as an administrator user otherwise you can get accessed denied trying to log someone out. Hope this helps!

This solution works great and allows for filtering on pretty much any criteria, such as partial username matches, or disconnected sessions only. You can wrap the whole thing in another foreach loop to run against multiple servers, too.
– cscrackerSep 21 '16 at 19:56

What does the '^' in the '^ SESSIONNAME' section on the second line do here? Curious as it seems to work with our without.
– HDCerberusFeb 13 at 22:22

It is a regular expression character which means beginning of line or beginning of string. Fairly universal across most regex implementations out there. Here's a topic about this very thing. It may not be necessary, but can help to make matches more specific in some cases. stackoverflow.com/questions/5516119/…
– Jason SlobotskiFeb 15 at 14:59

This is oldschool and predates PowerShell, but I have used the qwinsta / rwinsta combo for YEARS to remotely log off stale RDP sessions. It's built in on at least Windows XP and forward (possibly earlier)

the try/catch is used when there are no users are on the server, and the query returns an error. however, you could drop the 2>&1 part, and remove the try/catch if you don't mind seeing the error string

select -skip 1 removes the header line

the inner foreach logs off each user

($_ -split "\s+") splits the string to an array with just text items

[-6] index gets session ID and is the 6th string counting from the reverse of the array, you need to do this because the query output will have either 8 or 9 elements depending if the users connected or disconnected from the terminal session

Since we're in the PowerShell area, it's extra useful if we can return a proper PowerShell object ...

I personally like this method of parsing, for the terseness:

((quser) -replace '^>', '') -replace '\s{2,}', ',' | ConvertFrom-Csv

Note: this doesn't account for disconnected ("disc") users, but works well if you just want to get a quick list of users and don't care about the rest of the information. I just wanted a list and didn't care if they were currently disconnected.

If you do care about the rest of the data it's just a little more complex: