0

Get Logged In Users Using Powershell

A while back I posted my initial script to find the users that are logged into a server and log them off remotely. That was several years ago and I thought I would take another crack at it to try to improve the speed, improve the formatting and add some dedicated switches with a bit more flexibility. Lastly, I wanted to change that ugly, unconventional name to something more Powershell approved. I call this new function Get Logged In Users.

 
The underlying structure is still going to be using query session so that hasn’t changed. What has changed is now we can specify a specific user or find where a user is logged on in a domain. Another note is the ability to log them off using a simple switch so that can definitely come in handy if you’re checking a log of systems.

Get Logged In Users Using Powershell

Looking back I don’t know why I added the ActiveDirectory Module and made it run as an administrator. That is simply not needed and not required to run this function. However, I would highly recommend you run this on a Windows 10 machine or Server 2016 and later with Powershell 5 because well let’s face it, we’re in 2020.

Parameters

    -ComputerName

Description: This will specify the ComputerName that you would like to check.  If no ComputerName is specified, it will check the local computer.

    -UserName

Description: If the specified username is found logged into a machine, it will display it in the output.

    -LogOff

Description: If the logoff parameter is specified, it will logoff the user from the computer. It is recommended to run without the logoff switch to view the results first.

 

Function Get-LoggedInUser {
<#
.SYNOPSIS
    This will check the specified machine to see all users who are logged on.
    For updated help and examples refer to -Online version.

.NOTES
    Name: Get-LoggedInUser
    Author: theSysadminChannel
    Version: 2.0
    DateCreated: 2020-Apr-01


.LINK
    https://thesysadminchannel.com/get-logged-in-users-using-powershell/ -
    For updated help and examples refer to -Online version.



.PARAMETER ComputerName
    Specify a computername to see which users are logged into it.  If no computers are specified, it will default to the local computer.

.PARAMETER UserName
    If the specified username is found logged into a machine, it will display it in the output.

PARAMETER Logoff
    Logoff the users from the computers in your query. It is recommended to run without the logoff switch to view the results.

.EXAMPLE
    Get-LoggedInUser -ComputerName Server01

    Display all the users that are logged in server01

.EXAMPLE
    Get-LoggedInUser -ComputerName Server01, Server02 -UserName jsmith

    Display if the user, jsmith, is logged into server01 and/or server02

.EXAMPLE
    Get-LoggedInUser -ComputerName $ComputerList -Logoff

    Logoff all the users that are logged into the computers in the ComputerList array

.EXAMPLE
    Get-LoggedInUser -ComputerName $ComputerList -SamAccountName jsmith -Logoff

    If jsmith is logged into a computer in the $ComputerList array, it will log them out.

#>

    [CmdletBinding(DefaultParameterSetName="Default")]
        param(
            [Parameter(
                Mandatory = $false,
                ValueFromPipeline=$true,
                ValueFromPipelineByPropertyName=$true,
                Position=0
            )]
            [string[]] $ComputerName = $env:COMPUTERNAME,


            [Parameter(
                Mandatory = $false
            )]
            [Alias("SamAccountName")]
            [string]   $UserName,


            [Parameter(
                Mandatory = $false
            )]
            [switch]   $Logoff
        )

    BEGIN {}

    PROCESS {
        Foreach ($Computer in $ComputerName) {
            try {
                $ExplorerProcess = Get-WmiObject Win32_Process -Filter "Name = 'explorer.exe'" -ComputerName $Computer -ErrorAction Stop
                $Computer = $Computer.ToUpper()
                if ($ExplorerProcess) {
                    $UserList = $ExplorerProcess.GetOwner() | Where-Object {$_.ReturnValue -eq 0} | select -ExpandProperty User
                    if ($ExplorerProcess.GetOwner() | Where-Object {$_.ReturnValue -ne 0}) {
                        Write-Warning "Other users are logged in to $($Computer) but couldn't pull the details.  Consider running as an administrator."
                    }

                    if (-not $PSBoundParameters.ContainsKey("UserName") -and -not $PSBoundParameters.ContainsKey("Logoff")) {
                        foreach ($User in $UserList) {
                            $User = $User.ToLower()
                            $Session = (query session $User /Server:$Computer | Select-String -Pattern $User -ErrorAction Stop).ToString().Trim()
                            $Session = $Session -replace '\s+', ' '
                            $Session = $Session -replace '>', ''

                            if ($Session.Split(' ')[2] -cne "Disc") {
                                [PSCustomObject]@{
                                    ComputerName = $Computer
                                    UserName     = $User.Replace('{}','')
                                    SessionID    = $Session.Split(' ')[2]
                                    SessionState = $Session.Split(' ')[3]
                                }
                              } else {
                                [PSCustomObject]@{
                                    ComputerName = $Computer
                                    UserName     = $User.Replace('{}','')
                                    SessionID    = $Session.Split(' ')[1]
                                    SessionState = 'Disconnected'
                                }
                            }
                        }
                    } #End Default PSBoundParameter Block

                    if ($PSBoundParameters.ContainsKey("UserName") -and -not $PSBoundParameters.ContainsKey("Logoff")) {
                        foreach ($User in $UserList) {
                            if ($User -eq $UserName) {
                                $User = $User.ToLower()
                                $Session = (query session $User /Server:$Computer | Select-String -Pattern $User -ErrorAction Stop).ToString().Trim()
                                $Session = $Session -replace '\s+', ' '
                                $Session = $Session -replace '>', ''

                                if ($Session.Split(' ')[2] -cne "Disc") {
                                    [PSCustomObject]@{
                                        ComputerName = $Computer
                                        UserName     = $User.Replace('{}','')
                                        SessionID    = $Session.Split(' ')[2]
                                        SessionState = $Session.Split(' ')[3]
                                    }
                                  } else {
                                    [PSCustomObject]@{
                                        ComputerName = $Computer
                                        UserName     = $User.Replace('{}','')
                                        SessionID    = $Session.Split(' ')[1]
                                        SessionState = 'Disconnected'
                                    }
                                }
                            }
                        }
                    } #End UserName PSBoundParameter Block

                    if ($PSBoundParameters.ContainsKey("Logoff") -and -not $PSBoundParameters.ContainsKey("UserName")) {
                        foreach ($User in $UserList) {
                            $User = $User.ToLower()
                            $Session = (query session $User /Server:$Computer | Select-String -Pattern $User -ErrorAction Stop).ToString().Trim()
                            $Session = $Session -replace '\s+', ' '
                            $Session = $Session -replace '>', ''

                            if ($Session.Split(' ')[2] -cne "Disc") {
                                LogOff.exe /server:$Computer ($Session.Split(' ')[2])

                                [PSCustomObject]@{
                                    ComputerName = $Computer
                                    UserName     = $User.Replace('{}','')
                                    SessionID    = $Session.Split(' ')[2]
                                    SessionState = 'LoggingOff'
                                }
                            } else {
                                LogOff.exe /server:$Computer ($Session.Split(' ')[1])

                                [PSCustomObject]@{
                                    ComputerName = $Computer
                                    UserName     = $User.Replace('{}','')
                                    SessionID    = $Session.Split(' ')[1]
                                    SessionState = 'LoggingOff'
                                }
                            }
                        }
                    } #End Logoff PSBoundParameter Block

                    if ($PSBoundParameters.ContainsKey("Logoff") -and $PSBoundParameters.ContainsKey("UserName")) {
                        foreach ($User in $UserList) {
                            if ($User -eq $UserName) {
                                $User = $User.ToLower()
                                $Session = (query session $User /Server:$Computer | Select-String -Pattern $User -ErrorAction Stop).ToString().Trim()
                                $Session = $Session -replace '\s+', ' '
                                $Session = $Session -replace '>', ''

                                if ($Session.Split(' ')[2] -cne "Disc") {
                                    LogOff.exe /server:$Computer ($Session.Split(' ')[2])

                                    [PSCustomObject]@{
                                        ComputerName = $Computer
                                        UserName     = $User.Replace('{}','')
                                        SessionID    = $Session.Split(' ')[2]
                                        SessionState = 'LoggingOff'
                                    }
                                } else {
                                    LogOff.exe /server:$Computer ($Session.Split(' ')[1])

                                    [PSCustomObject]@{
                                        ComputerName = $Computer
                                        UserName     = $User.Replace('{}','')
                                        SessionID    = $Session.Split(' ')[1]
                                        SessionState = 'LoggingOff'
                                    }
                                }
                            }
                        }
                    } #End Logoff PSBoundParameter Block
                }

            } catch {
                Write-Error "$($Computer.ToUpper()) - $($_.Exception.Message)"

            }
        }
    }

    END {}
}

 

Get-LoggedInUser GIF
 

How To Run Get Logged In User Powershell Script

In order to the run the script there are a couple of things you need to do.  First and foremost, you need to set your execution policy to RemoteSigned or bypass.  This is a standard with running any Powershell script.

Next you need to dot source the script since it is a function.  To dot source the script do the following:

  • Copy the script above and save it any location. In this example I’ll save it to my C:\_Scripts folder.
  • Within the Powershell Window type: . .\_Scripts\Get-LoggedInUser.ps1 – Note the two dots before the backslash.

 

Get Logged On Users On Remote Computers

The best thing I love about this script is your ability to get who is logged into a remote computer. This mitigates the need to physically log into computer and checking that way. Since this Powershell script allows you to query remote servers and computers, it makes it highly automatable and very scalable. Using this script, you can check 1 server or 1,000 servers and it would be the same amount of effort for the person who is running it. It’s awesome and I love how you can do it all from your own Windows 10 computer.

You can also find where a user is logged on in a domain very easily. Depending on how many machines you’re going to be iterating through, it can obviously take some time but it can be done. Here is a simple code snippet of how to get where a user is logged in to.

PS C:\> . .\_Scripts\Get-LoggedInUser.ps1
PS C:\>
PS C:\> $ComputerList = Get-ADComputer -Filter {OperatingSystem -like "*Server*"} -Properties OperatingSystem | select -
ExpandProperty Name
PS C:\>
PS C:\> Get-LoggedInUser -ComputerName $ComputerList -UserName pcontreras -ErrorAction SilentlyContinue

ComputerName UserName   SessionID SessionState
------------ --------   --------- ------------
PAC-DC01     pcontreras 5         Active
PAC-ADC01    pcontreras 2         Active


PS C:\>

dot source get logged in user

ErrorAction SilentlyContinue is used to suppress connection errors and display clean output

 

So there you have it, a quick and easy solution to a problem that many IT Administrators have come across in their sysadmin journey. I am well aware that you can also do this via group policy if you wanted to go that route, or you can do this via some GUI tool but I always like to get my hands dirty with Powershell.

Thanks again for taking the time to visit and go ahead and drop a comment if you have any questions about the script or its intended fuctions. Also, don’t forget to check out our Youtube Channel for visual video content and our own personal Powershell gallery full of real world scripts.

Paul

Hi, my name is Paul and I am a Sysadmin who enjoys working on various technologies from Microsoft, VMWare, Cisco and many others. Join me as I document my trials and tribulations of the daily grind of System Administration.