0

How To Find Users Logged Into A Server – Log User Off Remotely

Time and time again we have admins in our environment that connect to a remote desktop session, do what they need to do. And instead of logging off, they simply just close the RDP session. Leaving the user logged on until the cows come home.  I’ve come across this so many times in my environment (guilty of it myself) that I decided to put my Powershell abilities to work and create a script to remotely check who is logged into a server and log them off. This Powershell script gives you the option to see who is logged into a server and if you specified a username parameter it will Find Users Logged Into A Server.  It works perfect for Server 2012 R2 and Server 2016.

Requirements

In order to run this successfully, you need to have the following:

  • The Active Directory Module must be installed on the computer.
  • Powershell Version 3.0 or greater.
  • Run the Powershell Windows as an administrator.

The script actually will not run if the requirements are not met.

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: This will specify a username that you would like to check.  If a username is specified, it will only filter said username.  The default is the currently logged on user.

    -LogOff

Description: If the logoff parameter is specified, it will logoff the user from the computer.

    -LogErrors

Description: If the LogErrors parameter is specified, it will log any errors that occurred during the run.  The default location is the users desktop.

 

Examples

Example 1: The default option is to check the current user and current computer.

PS C:\> Get-UsersAndLogOffComputers

Computer  : PAC-WIN1001
Username  : pcontreras
State     : Active
Session   : console
SessionID : 2

Get-UsersAndLogOffComputers

 

 

    Example 2: Specify a computername or multiple computernames seperated by a comma.

PS C:\> Get-UsersAndLogOffComputers -ComputerName PAC-FS01, PAC-SCCM01

Computer  : PAC-FS01
Username  : pcontreras
State     : Active
Session   : rdp-tcp#8
SessionID : 3

Computer  : PAC-SCCM01
Username  : pcontreras
State     : Disconnected
Session   : Idle
SessionID : 3

Get-UsersAndLogOffComputers -ComputerName

PAC-FS01 and PAC-SCCM01 were both specified and results were outputted. As you can see PAC-FS01 has an active session and PAC-SCCM01 has an Idle session. The Idle session means someone RDP’d in and disconnected instead of logging off.

 

    Example 3: Specify multiple computernames and a username.

PS C:\> Get-UsersAndLogOffComputers -ComputerName PAC-FS01, PAC-SCCM01 -Username DJones

Computer  : PAC-FS01
Username  : DJones
State     : Active
Session   : console
SessionID : 1

Get-UsersAndLogOffComputers-ComputerName-Username

The username DJones was specified and it was found logged into PAC-FS01. PAC-SCCM01 didn’t find a match so nothing was outputted.

 

    Example 4: Specify the username DJones and log it off the computer named PAC-FS01.

PS C:\> Get-UsersAndLogOffComputers -ComputerName PAC-FS01 -Username DJones -Logoff

Computer  : PAC-FS01
Username  : DJones
State     : Active
Session   : console
SessionID : 1

Get-UsersAndLogOffComputers-ComputerName-Username-LogOffThe same output will occur with the -Logoff Switch, however it will log the specified user off as long as it has admin rights to that machine.

 

    Example 5: Log the errors (if any) to give you a better idea of what the issue is.

PS C:\> Get-UsersAndLogOffComputers -ComputerName PAC-FS01, DoesntExist -Username DJones -LogErrors

Get-UsersAndLogOffComputers-ComputerName-Username-LogErrorsIn this example I specified the computer names PAC-FS01 and DoesntExist.  The username DJones doesn’t have rights to the server so the error that was logged shows Access is denied. The “Doesntexist” computer was not found and obviously not online so the error that was logged was “The RPC server is unavailable.”  The default path for the error log file is going to be the users desktop.

 

Script To Find Users Logged Into A Server – Log User Off Remotely

Great, so now that have the parameters and the examples out of the way, let’s get to the actual script.

Function Get-UsersAndLogOffComputers {

#requires -Module ActiveDirectory
#requires -RunAsAdministrator
#requires -Version 3.0

<#
.SYNOPSIS
    This will check to see if a user is logged on to a server and if specified, log them off.
    For updated help and examples refer to -Online version.

.DESCRIPTION
    This will check to see if a user is logged on to a server and if specified, log them off.
    For updated help and examples refer to -Online version.

.NOTES   
    Name: Get-UsersAndLogOffComputers
    Author: The Sysadmin Channel
    Version: 1.01
    DateCreated: 2017-Apr-01
    DateUpdated: 2017-Apr-09

.LINK
    https://thesysadminchannel.com/find-users-logged-into-a-server-and-log-them-off-remotely/ -
    For updated help and examples refer to -Online version.

#>

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

            [Parameter()]
            [string]   $Username = $env:USERNAME,

            [Parameter()]
            [switch]   $Logoff,

            [Parameter()]
            [switch]   $LogErrors
     
        )

    BEGIN {
        $ErrorLogFile = "$env:USERPROFILE\Desktop\Get-UsersAndLogOffComputers.txt"
        if (Test-Path $ErrorLogFile) {Remove-Item $ErrorLogFile}
    }

    PROCESS {
        Foreach ($Computer in $ComputerName) {
            try {
                $ExplorerProcess = Get-WmiObject Win32_Process -Filter "Name = 'explorer.exe'" -ComputerName $Computer -EA Stop
                    if ($ExplorerProcess) {
                        $ExplorerProcess = $ExplorerProcess.GetOwner().User
                        foreach ($Person in $ExplorerProcess) {
                            if ($Username -eq $Person) {
                                $Session = (query session $Username /Server:$Computer | Select-String -Pattern $Username -EA Stop).ToString().Trim()
                                $Session = $Session -replace '\s+', ' '
                                $Session = $Session -replace '>', ''

                                    if ($Session.Split(' ')[2] -cne "Disc") {
                                        $Properties = @{Computer  = $Computer
                                                        Username  = $Username.Replace('{}','')
                                                        Session   = $Session.Split(' ')[0]
                                                        SessionID = $Session.Split(' ')[2]
                                                        State     = $Session.Split(' ')[3]
                                                        }
                                    } else {
                                        $Properties = @{Computer  = $Computer
                                                        Username  = $Username.Replace('{}','')
                                                        Session   = 'Idle'
                                                        SessionID = $Session.Split(' ')[1]
                                                        State     = 'Disconnected'
                                                        }
                        
                                    }
                                $Object = New-Object -TypeName PSObject -Property $Properties | Select Computer, Username, State, Session, SessionID
                            } 
                        }
                    } 

            } catch { 
                $ErrorMessage = $Computer + " Error: " + $_.Exception.Message

            } finally {
                if ($ErrorMessage -and $LogErrors) {
                        Write-Output $ErrorMessage | Out-File $ErrorLogFile -Append
                        $ErrorMessage = $null
                }

                if ($Logoff -and $Object.SessionID) {
                    LogOff.exe /server:$Computer $Object.SessionID
                }

            Write-Output $Object
            $Object = $null
            }
        }
    }

    END {}

}

 

Log user off the entire domain or just all servers

Since this script allows inputs for multiple objects, we can easily pipe in an array of Servers or computers in general.

Getting all the Servers in the domain and seeing if the user DJones is logged on. Again we can use the -LogOff parameter to log the user out. If you have more 100 or 200 hundred servers I would probably make the filter a little smaller so use with a bit of caution.

#Get all servers and enumerate through each one to see if the user is logged in.
$Servers = Get-ADComputer -Filter {(OperatingSystem -like "*Server*") -and (Enabled -eq $true)} -Properties OperatingSystem | select -ExpandProperty Name | Sort-Object
Get-UsersAndLogOffComputers -ComputerName $Servers -Username DJones

#Get every computer object in the domain that is enabled and check to see if the user is logged in. 
$AllComputers = Get-ADComputer -Filter {Enabled -eq $true} | select -ExpandProperty Name | Sort-Object
Get-UsersAndLogOffComputers -ComputerName $AllComputers -Username DJones

How to run the Script

In order to the run the script there are a couple of things you need to do.  First and foremost, set your execution policy to RemoteSigned.  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 running as Administrator type: . .\_Scripts\Get-UsersAndLogOffComputers.ps1 – Note the two dots before the backslash.

Get-UsersAndLogOffComputers DotSource

Now you’re all set to call the function and run any of the parameters listed above.

Video and Explanation of how to Find Users Logged Into A Server


 

If you have any trouble dot sourcing the script or find any bugs please let me know in the comments section and I’ll be happy to update it.

 

If you’re looking to expand your Powershell knowledge check out Don Jones Learn Powershell In a Month Of Lunches Book and I hope this article to Find Users Logged Into A Server was informative and if you need to log user off remotely hopefully you will use this script.

How To Find Users Logged Into A Server – Log User Off Remotely
4.9 (97.04%) 27 votes

Paul Contreras

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.