Powershell script to see currently logged in users (domain and machine) + status (active, idle, away)

312,307

Solution 1

In search of this same solution, I found what I needed under a different question in stackoverflow: Powershell-log-off-remote-session. The below one line will return a list of logged on users.

query user /server:$SERVER

Solution 2

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:

(((quser) -replace '^>', '') -replace '\s{2,}', ',').Trim() | ForEach-Object {
    if ($_.Split(',').Count -eq 5) {
        Write-Output ($_ -replace '(^[^,]+)', '$1,')
    } else {
        Write-Output $_
    }
} | ConvertFrom-Csv

I take it a step farther and give you a very clean object on my blog.

I ended up making this into a module.

Solution 3

There's no "simple command" to do that. You can write a function, or take your choice of several that are available online in various code repositories. I use this:

function get-loggedonuser ($computername){

#mjolinor 3/17/10

$regexa = '.+Domain="(.+)",Name="(.+)"$'
$regexd = '.+LogonId="(\d+)"$'

$logontype = @{
"0"="Local System"
"2"="Interactive" #(Local logon)
"3"="Network" # (Remote logon)
"4"="Batch" # (Scheduled task)
"5"="Service" # (Service account logon)
"7"="Unlock" #(Screen saver)
"8"="NetworkCleartext" # (Cleartext network logon)
"9"="NewCredentials" #(RunAs using alternate credentials)
"10"="RemoteInteractive" #(RDP\TS\RemoteAssistance)
"11"="CachedInteractive" #(Local w\cached credentials)
}

$logon_sessions = @(gwmi win32_logonsession -ComputerName $computername)
$logon_users = @(gwmi win32_loggedonuser -ComputerName $computername)

$session_user = @{}

$logon_users |% {
$_.antecedent -match $regexa > $nul
$username = $matches[1] + "\" + $matches[2]
$_.dependent -match $regexd > $nul
$session = $matches[1]
$session_user[$session] += $username
}


$logon_sessions |%{
$starttime = [management.managementdatetimeconverter]::todatetime($_.starttime)

$loggedonuser = New-Object -TypeName psobject
$loggedonuser | Add-Member -MemberType NoteProperty -Name "Session" -Value $_.logonid
$loggedonuser | Add-Member -MemberType NoteProperty -Name "User" -Value $session_user[$_.logonid]
$loggedonuser | Add-Member -MemberType NoteProperty -Name "Type" -Value $logontype[$_.logontype.tostring()]
$loggedonuser | Add-Member -MemberType NoteProperty -Name "Auth" -Value $_.authenticationpackage
$loggedonuser | Add-Member -MemberType NoteProperty -Name "StartTime" -Value $starttime

$loggedonuser
}

}

Solution 4

Maybe you can do something with

get-process -includeusername

Solution 5

If you want to find interactively logged on users, I found a great tip here :https://p0w3rsh3ll.wordpress.com/2012/02/03/get-logged-on-users/ (Win32_ComputerSystem did not help me)

$explorerprocesses = @(Get-WmiObject -Query "Select * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue)
If ($explorerprocesses.Count -eq 0)
{
    "No explorer process found / Nobody interactively logged on"
}
Else
{
    ForEach ($i in $explorerprocesses)
    {
        $Username = $i.GetOwner().User
        $Domain = $i.GetOwner().Domain
        Write-Host "$Domain\$Username logged on since: $($i.ConvertToDateTime($i.CreationDate))"
    }
}
Share:
312,307
RayofCommand
Author by

RayofCommand

new to programming and scripting. 2013/06/21 I do enjoy: Powershell ServiceNow

Updated on July 09, 2022

Comments

  • RayofCommand
    RayofCommand almost 2 years

    I am searching for a simple command to see logged on users on server. I know this one :

    Get-WmiObject -Class win32_computersystem
    

    but this will not provide me the info I need. It returns : domain Manufactureer Model Name (Machine name) PrimaryOwnerName TotalPhysicalMemory

    I run Powershell 3.0 on a Windows 2012 server.

    Also

    Get-WmiObject Win32_LoggedOnUser -ComputerName $Computer | Select Antecedent -Unique
    

    gives me not the exact answers I need. I would love to see as well the idle time, or if they are active or away.

  • RayofCommand
    RayofCommand about 10 years
    I added the missing } in the end and changed the computername variable and set it to my hostname. But still i can't make this run. somehow it tries to use my machinename as cmdlet. If i explicitly Set-Variable -Name computername -Value “mymachinename” i get and RPC server is unavailable. I am still newbie, what do i miss?
  • mjolinor
    mjolinor about 10 years
    Sorry about the missing bracket (copy/paste fail). Fixed. Not sure why it's not working. After the function is loaded, you should be able to just run" get-loggedonuser <computername>. For the local machine, you can run: get-loggedonuser localhost
  • RayofCommand
    RayofCommand about 10 years
    still wasn't able to make it work. even if i replace the $computername directly using my machinename or localhost i didnt get any result. Is there a way to see the info of how long the user is logged in?
  • mjolinor
    mjolinor about 10 years
    If you look at that function, you'll see it also returns the starttime of the session, so you can calculate from that. But that doesn't help if it won't work on your machine, and I can't reproduce the error your getting to debug it.
  • RayofCommand
    RayofCommand about 10 years
    hmm i think you missed 40% of your own script. i just took the one from you posted on technet page. this as well has the session start time
  • mjolinor
    mjolinor about 10 years
    You're right. That's what I get for copying code out of my profile. Sorry about that. I updated the answer. Does that code to what you need?
  • RayofCommand
    RayofCommand about 10 years
    yep. thanks. Unfortunately I am not now able to select only the RemoteInteractive Users, can you help me out :)?
  • mjolinor
    mjolinor about 10 years
    Simple Where-Object filter. Get-LoggedOnuser <machine> | Where {$_.LogonType -eq 'RemoteInteractive'}
  • RayofCommand
    RayofCommand about 10 years
    thanks. But we need to use Type instead of LogonType. now it works as expected
  • Aaron
    Aaron over 8 years
    Is there a way to just pull the usernames and throw them on one line? I don't care much to know the session and start time, etc for certain things.
  • Michael Trouw
    Michael Trouw over 8 years
    Fun fact: linux equivalent: the 'w' command. of course, with Winblows, nothing has to be simple if it can be complicated.
  • mjolinor
    mjolinor over 8 years
    Well, that's 30 seconds of my life I'll never get back.
  • shivshankar
    shivshankar about 8 years
    This is a much better solution than the accepted answer. The accepted answer gives you all the users that are running services and and applications, not active RDP sessions or console sessions.
  • Code Jockey
    Code Jockey about 8 years
    I would go ahead and agree that it is a better answer to the question, in that the OP wanted a simple command, and so I've upvoted it, but I was looking for more functionality and Google sent me here, so for my purposes, mjolinor's answer is more useful, so I've upvoted that one... hmmmm
  • Kumar Sambhav Pandey
    Kumar Sambhav Pandey almost 8 years
    @mjolinor Hi Your script is working fine but on running the same it shows only my name i.e. {Session : 39648199 Type : Local System Auth : StartTime : 1/1/1601 5:30:00 AM}. I want to see how many users are currently logged in and are active (say in last 30 minutes), how can I do that ? Could you please help me with that ?
  • Jaans
    Jaans almost 7 years
    Like the lateral thinking. I know it isn't the "correct" answer, but it does present a potential workaround solution. Get-Process -IncludeUserName | Select-Object -Unique -Property UserName
  • SamAndrew81
    SamAndrew81 almost 7 years
    Brilliant and exactly what I was looking for!
  • as9876
    as9876 over 6 years
    Unless the user is using a custom shell other than explorer.exe docs.microsoft.com/en-us/windows-hardware/customize/enterpri‌​se/…
  • user2305193
    user2305193 over 6 years
    doesn't give you the machine name?
  • KawaGreen
    KawaGreen about 6 years
    This needs more upvotes. Spent too long trying to get it to format the way I wanted.
  • Rakha
    Rakha almost 6 years
    Indeed, this is BRILLIANT!
  • Carl Walsh
    Carl Walsh over 5 years
    This listed 18 sessions, including some users as Interactive that aren't even logged in. Also, the sessions were in the millions, when I was expecting single-digits...
  • not2qubit
    not2qubit about 4 years
    This give me: query: The term 'query' is not recognized.... So what am I missing here?
  • not2qubit
    not2qubit about 4 years
    quser is not recognized under PS. What's missing?
  • VertigoRay
    VertigoRay almost 4 years
    Pulling the username off a process, other than your own, requires admin rights.
  • VertigoRay
    VertigoRay almost 4 years
    @not2qubit, are you running on Windows? If so, check your path. quser is an executable: C:\WINDOWS\system32\quser.exe. You can also try query user, it returns the exact same output. query is also an executable: C:\WINDOWS\system32\query.exe
  • not2qubit
    not2qubit almost 4 years
    @VertigoRay I don't have those *.exe files on my system... (Win8.1).
  • VertigoRay
    VertigoRay almost 4 years
    @not2qubit Home Edition? If so, it's likely the issue or your installation is corrupt or incomplete. For help on that: answers.microsoft.com/en-us/windows/forum/all/…
  • not2qubit
    not2qubit almost 4 years
    @VertigoRay No, that's not right. I don't have this command on Win10 (Home) either. So I think it might be a server specific command.
  • VertigoRay
    VertigoRay almost 4 years
    @not2qubit Like I said, it's not available on the Home SKUs. I have it available on Pro and Enterprise SKUs of Win10, and my brother confirmed that query user and quser are not available on Win10 1909 Home. Since you cannot RDP into a Home SKU, it's a bit irrelevant to run this command locally.
  • not2qubit
    not2qubit almost 4 years
    @VertigoRay Thanks, but that was not clear at all. Also, there are several other and better ways than RDP, so definitely not irrelevant.
  • VertigoRay
    VertigoRay almost 4 years
    @not2qubit Apologies for not being clear. I'm curious what your other/better ways are. Tools like VNC/Teamviewer/LogMeIn connect to the console session, and quser isn't the right tool for seeing if someone is connected via those services.
  • VertigoRay
    VertigoRay almost 4 years
    @not2qubit If you were not running Windows Home edition, you might be running PowerShell 32-bit on a 64-bit OS and unable to find quser. In which case, you would need to use SysNative to get to the real System32 folder: C:\Windows\SysNative\quser.exe
  • Hyon
    Hyon almost 4 years
    What version of Windows and Powershell are you running? Can you run "get-command query" and verify that it is located at c:\WINDOWS\system32\query.exe.
  • stackprotector
    stackprotector about 3 years
    This method does not list users, that are logged on via SSH (built-in OpenSSH).
  • dragonspeed
    dragonspeed over 2 years
    On my system - no idle time is designated as "none" and your script breaks. PS C:\WINDOWS\system32> query user USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME >some.user console 1 Active none 8/17/2021 5:32 AM Sorry - comment formatting won't show it as correctly formatted :(
  • Leon Bouquiet
    Leon Bouquiet over 2 years
    Ok, off the top of my head, you could try changing if($parts[5] -ne '.') into if(@('.', 'none') -notcontains $parts[5]) and see if that works?
  • dragonspeed
    dragonspeed over 2 years
    Changed it to: $(if($parts[5] -ne '.' -and $parts[5] -ne 'none') - All good - works for remote (although there is no "current" user in remote checking
  • Tilo
    Tilo over 2 years
    same Q as @user2305193 ; any way to see the client-name of the user who RDP (visible via Task Manager Users)
  • Tilo
    Tilo over 2 years
    for client-name see also other questions stackoverflow.com/q/48456277/1747983 ; seems PSTerminalServices has this option (first import module)
  • T-Heron
    T-Heron over 2 years
    Note that this requires Admin rights in order to run
  • AnrDaemon
    AnrDaemon about 2 years
    Which would not work, if user's shell is NOT explorer.exe (sorry for stating the obvious).