none
Logoff a specific user Powershell Script RRS feed

  • Question

  • Hey team

    I need to be able to log off a specified user.

    I am creating an automated process using MSP N-Central, which checks the remote computer to see if a particular user is logged on, if that user is logged on i need a powershell script to log them off. Most of the time they won't be the current user as the company i work for offers remote support for businesses so the client needs to be able to continue using their computer.

    In this case the account name will always be the same 

    So I guess what I'm asking is how to silently log out a user who is still logged on but is not the current user, using a powershell script, WITHOUT disrupting the current user

    Example: I've been working on a clients PC remotely, I forgot to log my account off before disconnecting the remote session. My client has now come along and started using the PC, I need to log off without the client knowing or being disrupted.

    My automation process will determine if my user is still logged on, if its not still logged on the automation process simply closes itself. If my user is still logged on it will run a powershell script to log the user off then the automation process will close itself. 

    Thursday, November 23, 2017 7:44 AM

Answers

  • Here is a script modified from Jaap Brassers Get-LoggedOnUser PowerShell script (Link) to do what you are looking for:

    <#
    .Synopsis
    Queries a computer to check for interactive sessions and logs out users
    
    .DESCRIPTION
    This script takes the output from the quser program and parses this to PowerShell objects
    
    .NOTES   
    Modified from original source - https://gallery.technet.microsoft.com/scriptcenter/Get-LoggedOnUser-Gathers-7cbe93ea
    
    .PARAMETER ComputerName
    The string or array of string for which a query will be executed
    
    .EXAMPLE
    .\Remove-LoggedOffUser.ps1 -ComputerName server01,server02
    
    Description:
    This will remotely log out disconnected users from specified computers
    #>
    param (
    	[CmdletBinding()]
    	[Parameter(ValueFromPipeline = $true,
    			   ValueFromPipelineByPropertyName = $true)]
    	[string[]]
    	$ComputerName = 'localhost'
    )
    begin {
    	$ErrorActionPreference = 'Stop'
    }
    
    process {
    	foreach ($Computer in $ComputerName) {
    		try {
    			quser /Server:$ComputerName | Select-Object -Skip 1 | ForEach-Object {
    				$CurrentLine = $_.Trim() -Replace '\s+', ' ' -Split '\s'
    				$UserName = $CurrentLine[0]
    				$UserID = $CurrentLine[1]
    				$UserActivity = $CurrentLine[2]
    				
    				# If session is disconnected, all processes will be closed and the user logged out
    				if ($UserActivity -match 'Disc') {
    					Get-Process | Select -Property ID, SessionID | Where-Object { $_.SessionID -eq $UserID } | ForEach-Object { Stop-Process -ID $_.ID -Force -ErrorAction SilentlyContinue }
    					Write-Warning "Logging off user $UserName"
    					Logoff $UserID
    				}
    			}
    		}
    		catch {
    			Write-Warning "Error occured - $($_.Exception.Message)"
    		}
    	}
    }

    In that instance it will stop all processes for disconnected users and log them out. If as you state you want a single user account to be targeted then replace this line:

    if ($UserActivity -match 'Disc') {

    with this

    if ($UserActivity -match 'Disc' -and $UserName -match "YourUser") {

    Note that due to the fact processes are stopped and the user logged out, data loss might occur where apps are open and documents not saved.

    Regards

    Maurice Daly
    Microsoft MVP | Enterprise Mobility
    SCConfigMgr.com

                   
    Thursday, November 23, 2017 3:41 PM
  • Here is a pretty flexible function that does it all.

    function Get-Quser{
        param(
            [string]$Username,
            [Parameter(
                ValueFromPipeline=$true,
                ValueFromPipelineByPropertyName=$true
            )]
            [Alias('Name','Computer','Server')] [string]$ComputerName = $env:COMPUTERNAME, [switch]$Logoff ) begin { $tmplt = @{ ComputerName = $null UserName = $null SessionName = $null SessionId = $null State = $null IdleTime = $null LogonTime = $null Error = $null } } process { $hash = $tmplt.Clone() # clear (gets an unused hash) $hash.ComputerName = $ComputerName try { quser /server:$Computer 2>&1 | Select-Object -Skip 1 | ForEach-Object { $hash.ComputerName = $Computer $hash.UserName = (-join $_[1 .. 20]).Trim() $hash.SessionName = (-join $_[23 .. 37]).Trim() $hash.SessionId = [int](-join $_[38 .. 44]) $hash.State = (-join $_[46 .. 53]).Trim() $hash.IdleTime = [datetime](-join $_[54 .. 63]).Trim() - [datetime]::Today $hash.LogonTime = [datetime](-join $_[65 .. ($_.Length - 1)]) } } catch { $hash.Error = $_ } if($username){ if($Username -eq $hash.Username){ if($Logoff){ Write-Warning "Logging off $($hash.Username) from $ComputerName" #logoff $hash.SessionId /SERVER:$computer } } }else{ [pscustomobject]$hash } Remove-Variable hash } } Get-Quser -Username jsmith -Logoff


    \_(ツ)_/


    Thursday, November 23, 2017 5:05 PM

All replies

  • Here is a script modified from Jaap Brassers Get-LoggedOnUser PowerShell script (Link) to do what you are looking for:

    <#
    .Synopsis
    Queries a computer to check for interactive sessions and logs out users
    
    .DESCRIPTION
    This script takes the output from the quser program and parses this to PowerShell objects
    
    .NOTES   
    Modified from original source - https://gallery.technet.microsoft.com/scriptcenter/Get-LoggedOnUser-Gathers-7cbe93ea
    
    .PARAMETER ComputerName
    The string or array of string for which a query will be executed
    
    .EXAMPLE
    .\Remove-LoggedOffUser.ps1 -ComputerName server01,server02
    
    Description:
    This will remotely log out disconnected users from specified computers
    #>
    param (
    	[CmdletBinding()]
    	[Parameter(ValueFromPipeline = $true,
    			   ValueFromPipelineByPropertyName = $true)]
    	[string[]]
    	$ComputerName = 'localhost'
    )
    begin {
    	$ErrorActionPreference = 'Stop'
    }
    
    process {
    	foreach ($Computer in $ComputerName) {
    		try {
    			quser /Server:$ComputerName | Select-Object -Skip 1 | ForEach-Object {
    				$CurrentLine = $_.Trim() -Replace '\s+', ' ' -Split '\s'
    				$UserName = $CurrentLine[0]
    				$UserID = $CurrentLine[1]
    				$UserActivity = $CurrentLine[2]
    				
    				# If session is disconnected, all processes will be closed and the user logged out
    				if ($UserActivity -match 'Disc') {
    					Get-Process | Select -Property ID, SessionID | Where-Object { $_.SessionID -eq $UserID } | ForEach-Object { Stop-Process -ID $_.ID -Force -ErrorAction SilentlyContinue }
    					Write-Warning "Logging off user $UserName"
    					Logoff $UserID
    				}
    			}
    		}
    		catch {
    			Write-Warning "Error occured - $($_.Exception.Message)"
    		}
    	}
    }

    In that instance it will stop all processes for disconnected users and log them out. If as you state you want a single user account to be targeted then replace this line:

    if ($UserActivity -match 'Disc') {

    with this

    if ($UserActivity -match 'Disc' -and $UserName -match "YourUser") {

    Note that due to the fact processes are stopped and the user logged out, data loss might occur where apps are open and documents not saved.

    Regards

    Maurice Daly
    Microsoft MVP | Enterprise Mobility
    SCConfigMgr.com

                   
    Thursday, November 23, 2017 3:41 PM
  • Here is a pretty flexible function that does it all.

    function Get-Quser{
        param(
            [string]$Username,
            [Parameter(
                ValueFromPipeline=$true,
                ValueFromPipelineByPropertyName=$true
            )]
            [Alias('Name','Computer','Server')] [string]$ComputerName = $env:COMPUTERNAME, [switch]$Logoff ) begin { $tmplt = @{ ComputerName = $null UserName = $null SessionName = $null SessionId = $null State = $null IdleTime = $null LogonTime = $null Error = $null } } process { $hash = $tmplt.Clone() # clear (gets an unused hash) $hash.ComputerName = $ComputerName try { quser /server:$Computer 2>&1 | Select-Object -Skip 1 | ForEach-Object { $hash.ComputerName = $Computer $hash.UserName = (-join $_[1 .. 20]).Trim() $hash.SessionName = (-join $_[23 .. 37]).Trim() $hash.SessionId = [int](-join $_[38 .. 44]) $hash.State = (-join $_[46 .. 53]).Trim() $hash.IdleTime = [datetime](-join $_[54 .. 63]).Trim() - [datetime]::Today $hash.LogonTime = [datetime](-join $_[65 .. ($_.Length - 1)]) } } catch { $hash.Error = $_ } if($username){ if($Username -eq $hash.Username){ if($Logoff){ Write-Warning "Logging off $($hash.Username) from $ComputerName" #logoff $hash.SessionId /SERVER:$computer } } }else{ [pscustomobject]$hash } Remove-Variable hash } } Get-Quser -Username jsmith -Logoff


    \_(ツ)_/


    Thursday, November 23, 2017 5:05 PM
  • Please check your code before posting.

    it's $Computer or $ComputerName on 'quser'?
    Logout on the executing server? You better add /Server:$Computer
    Was not nice to kill a service on your local machine.


    (: fcm :)

    Wednesday, December 11, 2019 2:37 PM