6

I am trying to get currently logged in users who has active session.

In the task manager, the list is crystal clear that there are two user sessions and one is active.

I want to query the same via Powershell. I tried few of the available commands Get-WmiObject Win32_LoggedOnUser | Select Antecedent -Unique which lists lot more users than I can even see [domain joined computer]

I am looking for the query which can give results exactly like Task Manager. enter image description here

RaceBase
  • 633
  • 4
  • 11
  • 24
  • 1
    What about `query user`? – duenni Mar 08 '17 at 15:55
  • @duenni seems right way. anyway to parse and get `Active users`. Seems like it's string output – RaceBase Mar 08 '17 at 15:57
  • Maybe this can help you http://superuser.com/q/587737/378809 – duenni Mar 08 '17 at 16:03
  • AFAIK there isn't a native way via PowerShell, I've looked for it in the past. See [Powershell get a value from 'query user' and not the headers etc](http://superuser.com/questions/587737/powershell-get-a-value-from-query-user-and-not-the-headers-etc?noredirect=1&lq=1) – Ƭᴇcʜιᴇ007 Mar 08 '17 at 18:13
  • @MagicallyDelicous, I am actually trying to execute some scripts in remote machine using remote powershell. If there's no active user, I am trying to reboot the machine. – RaceBase Mar 09 '17 at 06:07
  • Reddy - Get ready when it's time for spaghetti and remind me to get my machete so I can chop, chop, chop... psyche... What's the status on this? Did you read my comments too? – Vomit IT - Chunky Mess Style Mar 18 '17 at 06:20
  • @MagicallyDelicous I have done it differently http://stackoverflow.com/questions/42711592/getting-the-logged-in-user-in-powershell This works in all machines and not lang dependent and gives the right results – RaceBase Mar 20 '17 at 06:09
  • Oh, so you used some C# code in PS with the `Add-Type`... that was my second guess... **NOT**!! – Vomit IT - Chunky Mess Style Apr 28 '17 at 00:58

5 Answers5

3

The issue with Get-WmiObject Win32_LoggedOnUser | Select Antecedent -Unique is that it shows all sessions even those that have been closed since the last time the computer rebooted. The easiest way to poll sessions is unfortunately using the old executable query.exe.

You can convert the output of query.exe to objects using a bit of regex:

$Computer = $env:COMPUTERNAME
$Users = query user /server:$Computer 2>&1

$Users = $Users | ForEach-Object {
    (($_.trim() -replace ">" -replace "(?m)^([A-Za-z0-9]{3,})\s+(\d{1,2}\s+\w+)", '$1  none  $2' -replace "\s{2,}", "," -replace "none", $null))
} | ConvertFrom-Csv

foreach ($User in $Users)
{
    [PSCustomObject]@{
        ComputerName = $Computer
        Username = $User.USERNAME
        SessionState = $User.STATE.Replace("Disc", "Disconnected")
        SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
    } 
}

Which will give you output like this:

ComputerName Username SessionState SessionType
------------ -------- ------------ -----------
BSMITH-LT    bobsm    Active       console    

Taking it a lot further in to a function:

function Convert-QueryToObjects
{
    [CmdletBinding()]
    [Alias('QueryToObject')]
    [OutputType([PSCustomObject])]
    param
    (
        [Parameter(Mandatory = $false,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true,
                   Position = 0)]
        [Alias('ComputerName', 'Computer')]
        [string]
        $Name = $env:COMPUTERNAME
    )

    Process
    {
        Write-Verbose "Running query.exe against $Name."
        $Users = query user /server:$Name 2>&1

        if ($Users -like "*No User exists*")
        {
            # Handle no user's found returned from query.
            # Returned: 'No User exists for *'
            Write-Error "There were no users found on $Name : $Users"
            Write-Verbose "There were no users found on $Name."
        }
        elseif ($Users -like "*Error*")
        {
            # Handle errored returned by query.
            # Returned: 'Error ...<message>...'
            Write-Error "There was an error running query against $Name : $Users"
            Write-Verbose "There was an error running query against $Name."
        }
        elseif ($Users -eq $null -and $ErrorActionPreference -eq 'SilentlyContinue')
        {
            # Handdle null output called by -ErrorAction.
            Write-Verbose "Error action has supressed output from query.exe. Results were null."
        }
        else
        {
            Write-Verbose "Users found on $Name. Converting output from text."

            # Conversion logic. Handles the fact that the sessionname column may be populated or not.
            $Users = $Users | ForEach-Object {
                (($_.trim() -replace ">" -replace "(?m)^([A-Za-z0-9]{3,})\s+(\d{1,2}\s+\w+)", '$1  none  $2' -replace "\s{2,}", "," -replace "none", $null))
            } | ConvertFrom-Csv

            Write-Verbose "Generating output for $($Users.Count) users connected to $Name."

            # Output objects.
            foreach ($User in $Users)
            {
                Write-Verbose $User
                if ($VerbosePreference -eq 'Continue')
                {
                    # Add '| Out-Host' if -Verbose is tripped.
                    [PSCustomObject]@{
                        ComputerName = $Name
                        Username = $User.USERNAME
                        SessionState = $User.STATE.Replace("Disc", "Disconnected")
                        SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
                    } | Out-Host
                }
                else
                {
                    # Standard output.
                    [PSCustomObject]@{
                        ComputerName = $Name
                        Username = $User.USERNAME
                        SessionState = $User.STATE.Replace("Disc", "Disconnected")
                        SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
                    }
                }
            }
        }
    }
}

and now you can do things like: Get-ADComputer -Filter {Name -like "SERVER*"} | Convert-QueryToObjects | ? {$_.SessionState -eq 'Active'}

omniomi
  • 76
  • 7
  • 1
    the only problem is. The `quser` returns output in local language. This will be a problem if one wants to run on remote machines which might has different lang – RaceBase Mar 13 '17 at 02:27
  • You can modify the function to handle different languages but there sadly no real alternative ways to get the information you need. The only viable pure PowerShell method is to check for running explorer.exe processes on the remote machine but that doesn't distinguish between active and disconnected sessions. That said, now may be the time to consider standardizing the installation language of your servers and having users make use of Set-WinUILanguageOverride for their personal UI language needs. – omniomi Mar 13 '17 at 13:30
3

Here's how I do it. It doesn't work for rdp sessions though.

$out = query session | where {$_ -match 'console'}
$array = $out -split('\s+')
$consoleuser = $array[1]

Or:

$consoleuser = query session | select-string console | foreach { -split $_ } | 
  select -index 1
js2010
  • 575
  • 5
  • 6
1

This can be done with:

get-wmiobject -Class Win32_Computersystem | select Username
s0mm3r
  • 21
  • 1
  • It gives me empty result when I execute in remote machine from RDP :( – RaceBase Mar 08 '17 at 15:51
  • 1
    the wmi query only gets localy signed in users, to get rdp sessions try "qwinsta" here's a script i've got with one google search https://gallery.technet.microsoft.com/scriptcenter/PowerShell-script-to-Find-d2ba4252 – s0mm3r Mar 08 '17 at 16:04
1
Get-WmiObject Win32_Process -f 'Name="explorer.exe"'  |%  getowner  |% user
Donald Duck
  • 2,473
  • 10
  • 29
  • 45
alex
  • 31
  • 1
  • 6
    Surrounding this piece of code by some explanation would seriously improve your answer. – zx485 Apr 24 '20 at 17:38
  • This answer would indeed greatly benefits from some explanation/context. BUT I think it offers a new and nicer way to query currently logged-in users by searching for all Explorer.exe process and retrieving the user associated with it. It's quite clever actually, I like it. – Indigo Mar 07 '23 at 13:45
0

A little late to the party, but this is how I do it. I get the output from quser, replace tabs with commas and then convert the data from CSV to an object.

$QUserToRichObject = ((Invoke-Expression quser) -replace '\s{2,}', ',' | ConvertFrom-Csv)

If($QUserToRichObject){

    $UserSessions = @()

    ForEach($Record in $QUserToRichObject){

        # If the active session, remove the '>' character from Username value
        If($Record.USERNAME -Like ">*"){$Record.USERNAME = ($Record.USERNAME -Replace ">", "")}

        $UserSessions += @{
            Username        = [string]$Record.USERNAME
            SessionName     = [string]$Record.SESSIONNAME
            ID              = [string]$Record.ID
            State           = [string]$Record.STATE
            Idle            = [string]$Record.'IDLE TIME'
            LogonTime       = [string]$Record.'LOGON TIME'
        }
    }
}

$UserSessions

<#
Outputs:
Name                           Value                                                                                                                                                                           
----                           -----                                                                                                                                                                           
ID                             1                                                                                                                                                                               
SessionName                    console                                                                                                                                                                         
Idle                           none                                                                                                                                                                            
LogonTime                      04/11/2019 14:01                                                                                                                                                                
Username                       SomeUsername                                                                                                                                                                 
State                          Active
#>
Arbiter
  • 73
  • 1
  • 8