Search code examples
powershellautomationrdplogoff

Script to Log Off Specific Disconnected User via PS


I am currently working on a script to identify disconnected sessions X amount of days old, from a specific user account across the domain.

We have a tool in place which will be able to run this script across all selected machines, so there is no issue in selecting a target, as local host will be sufficient in this instance.

However, I am struggling with a few elements of the script as I am new to Powershell.

$userName = 'USERNAMEHERE'
$State = 'Disc'
$sessionId = ((quser /server:localhost | Where-Object { $_ -match $userName }{ $_ -match $State }{[datetime]$_."Idle Time" -le (Get-Date).AddDays(-1)})-split ' +')[3]
$sessionId
logoff $sessionId /server:localhost

The issue I am struggling with are:

  1. A positional parameter cannot be found that accepts argument "$_ -match $State" - is this a result of me trying to cram too much onto this line for Session ID? Or that State is not a valid parameter? Or another issue I am missing? From what I can gather, as State is not a key, so this is where I am running into trouble, but I'm not sure how to tackle it.

If I'm way off and need to adjust accordingly, I'd also be grateful to be informed of this.

Thanks Andy


Solution

  • Toby's suggestion is correct for dealing with the error message. If you want to output the session ID, you can run the following:

    $userName = 'username'
    $State = 'Disc'
    $sessions = (quser /server:localhost).TrimStart() -replace "\s{2,}",","
    $sessionIDs = $sessions | ForEach-Object {
        $SessionProperties = $_ -split ","  
        if ($SessionProperties[0] -eq $userName -and $SessionProperties[-3] -eq $state -and $SessionProperties[-2] -match "\+") { 
            $SessionProperties[-4]
        }
        }
    $sessionIDs
    

    The TrimStart() method removes the initial space/indent from the quser output.

    The -replace operator is doing some formatting. It is replacing consecutive spaces with commas. This is merely a self-made delimiter enabling better accessibility to the data.

    I chose to loop through $sessions because there could be times where the same user has multiple disconnected sessions. It should not ever happen, but Windows will be Windows.

    $SessionProperties is splitting each line of $sessions into an array. Each partial string between the commas is an element in the array. For accessing the elements of the array, I'm using a variety of index numbers. [0] is the first element, which should always be the username. The negative indices like [-4] are counting backwards from the end of the array. [-1] represents the last index of the array whereas [-2] would be the second to last element and so on. The reason I chose the negative indexes is because sometimes the SESSIONNAME of the quser output is spaces, which makes the -split operator create an array with one less element. Doing this allows you to change the $State variable in the future to something else whether or not SESSIONNAME contains any useful data.

    The -match operator is matching on character +. The + proceeds the number of days. Since you are searching for at least one day old idle times, this makes the regex match simpler. This will need to be changed if you ever want to match in idle times less than a day.

    For information about -match, see For information about -split, see about_Split

    For information about -replace and -match, see about_Comparison_Operators

    For operators in general, you can peruse about_Operators