Get Logged on users

The powershell MVP Richard Siddaway posted recently on his blog a way to list all currently users who have a session loaded on a computer being interactive or not. Note that it requires admin rights and the it fails to display domain users if it’s unable to resolve it using a domain controller.

But, how do we get only users who logged on interactively ?

(get-wmiobject -class Win32_ComputerSystem).Username

But this has a limitation as the following page on MSDN about the Win32_ComputerSystem states that

Name of a user that is logged on currently. This property must have a value. In a terminal services session, UserName returns the name of the user that is logged on to the console—not the user logged on during the terminal service session.

It is also not as reliable as it seems. It may return an empty value if the user is connected using remote desktop.

We could also query the Win32_LoggedOnUser which seems to be promising.

# To obtain Domain\Username format, we can do:
Get-WmiObject -Class Win32_LoggedOnUser | ForEach-Object { 
    Write-Host -Object (($_.Antecedent.ToString() -split '[\=\"]')[2] + "\" +  ($_.Antecedent.ToString() -split '[\=\"]')[5])
}

# Or more simply if we don't care too much about the format being displayed
Get-WmiObject -Class Win32_LoggedOnUser | ForEach-Object { Write-Host -NoNewline -Object (($_.Antecedent.ToString() -split '[\=\"]')[2,5] + "`n")}

Unfortunately, we get more results than expected.

Well, in this case, what I prefer to do is the following. If someone opened an interactive session on a computer, I can assume that the explorer was loaded. So the idea is to get the owner of each explorer.exe process and voilà.

$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
        $Domain + "\" + $Username + " logged on since: " + ($i.ConvertToDateTime($i.CreationDate))
    }
}
Advertisements

10 thoughts on “Get Logged on users

  1. Pingback: Get a list of machine names and logged in user(s) | use-powershell

  2. Pingback: Get a list of machine names and logged on or active user(s) | prgmr.io

  3. Pingback: Get a list of machine names and logged on or active user(s) « prgmr.io

    • Yes, there is of course. It just depends on how your remote computers are configured.
      What version of powershell do you have on target computers?
      Is powershell remoting enabled?
      Is the firewall on target computers enabled to allow either powershell remoting or wmi?

      • Quite a few of the computer have Powershell V2. Some do have V3 though.
        Powershell remoting is enabled and and WINRM is enabled also.

      • Fill-in a file named computers.txt with target computer names and you could do somthing like this:

        
        # 1. Create scriptblock to target computer will execute
        $SB = {
        
            $explorerprocesses = @(Get-WmiObject -Query "Select * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue)
            if ($explorerprocesses.Count -eq 0)    {
                    New-Object -TypeName PSObject -Property @{
                        ComputerName = $env:COMPUTERNAME;
                        Username = [string]::Empty
                        LoggedOnSince = [string]::Empty
                    }
            } else {
                foreach ($i in $explorerprocesses)    {
                    $Username = $i.GetOwner().User
                    $Domain = $i.GetOwner().Domain
                    New-Object -TypeName PSObject -Property @{
                        ComputerName = $env:COMPUTERNAME ;
                        Username = '{0}\{1}' -f $Domain,$Username ;
                        LoggedOnSince  = ($i.ConvertToDateTime($i.CreationDate)) ;
                    }
                }
            }
        } # endof scriptblock
        
        # 2. Create an empty array to store results
        $results = @()
        
        # 3. Query target computers using PSRemoting
        Get-content Computers.txt | ForEach-Object -Process {
            $computer = $_
            try {
                $results += Invoke-Command -ComputerName $Computer -ScriptBlock $SB -ErrorAction Stop
            } catch {
                Write-Warning -Message "Faild to use PSremoting on $Computer because $($_.Exception.Message)"
            }
        }
        
        # 4. Display the results
        $results | Select ComputerName,Username,LoggedOnSince | ft -AutoSize
        
  4. Pingback: Automatic Shutdown If No One Logs In | Etdwh.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s