5

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

8
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'}

2
  • 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 2: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
1

This can be done with:

get-wmiobject -Class Win32_Computersystem | select Username
2
  • It gives me empty result when I execute in remote machine from RDP :(
    – RaceBase
    Mar 8 '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 gallery.technet.microsoft.com/scriptcenter/…
    – s0mm3r
    Mar 8 '17 at 16:04
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
#>
-1

gwmi win32_process -f 'Name = "explorer.exe"'|% getowner|% user

1
  • 3
    Surrounding this piece of code by some explanation would seriously improve your answer.
    – zx485
    Apr 24 '20 at 17:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.