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))
    }
}

21 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

    • Thanks for reporting the issue but I need more info to be able to help you.
      What version of Windows do run?
      What version of PowerShell?
      Do you run the code as an administrator (with admin privileges and an elevated powershell prompt)?
      If you can, could you please attach a screenshot of your code and the error? (You can blur some part of it if it contains confidential data)

  5. Hi Wesley,

    This is a bit old, but I will give it a try. I am looking for a way to get the status of every loggedin User Sessions, and logoff every session that has a idle status of 2 hours +. Do you have any idea, how can I do that ? I have been searching in the W32_ kind of “libraries” Im a powershell newbie (and French x) ), so EZ on the rocks throw ahah

  6. Pingback: Hi there,While browsing one of the forums, I came – Coin news

  7. Pingback: Descubra quién está iniciando sesión en una computadora en PowerShell [Download] - TecnoTraffic

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.