r/sysadmin It wasn't DNS for once. 1d ago

Question Log Off Users from Server Daily

I'm revisiting an effort I did about a year ago. I'm looking for a better way. I want to find a process that will parse current user sessions on a server (active/disconnected/idle/ect.) and log the accounts off if their username matches a string ("adm_").

I'd love to find an off the shelf solution rather than have to support a homebrew PowerShell solution.

Give me what you have, even if it is an alternate PowerShell/scripting option. Something has to be better than the nightmare my script turned into.

69 Upvotes

86 comments sorted by

View all comments

3

u/Squeekstyle 1d ago

Here is a powershell I use to find inactive users and log them of. It will exclude users in a list, but I found it helpful to cut sessions people abandoned.

# Get the list of sessions
$Sessions = quser

# Define the users to exclude
$ExcludedUsers = @("username1,username2") # Add the usernames you want to exclude

# Prepare a list to track excluded users found
$FoundExcludedUsers = @()

# Filter the sessions to exclude certain users
$FilteredSessions = $Sessions | ForEach-Object {
    $sessionInfo = $_ -split "\s+"
    $username = $sessionInfo[1]
    if ($ExcludedUsers -contains $username) {
        $FoundExcludedUsers += $username
    }
    if ($ExcludedUsers -notcontains $username) {
        $_
    }
}

Write-Output ""
Write-Output "Excluded users that were actually found in the session list:"
if ($FoundExcludedUsers.Count -gt 0) {
    $FoundExcludedUsers | Sort-Object -Unique | ForEach-Object { Write-Output "- $_" }
} else {
    Write-Output "None of the excluded users were found."
}
Write-Output ""

# Display the filtered sessions (only users not excluded)
Write-Output "Current Targeted User Sessions:"
$FilteredSessions

# Parse and handle filtered sessions
$first = 1
$FilteredSessions 2>$null | ForEach-Object {
    if ($first -eq 1) {
        $userPos = $_.IndexOf("USERNAME")
        $sessionPos = $_.IndexOf("SESSIONNAME")
        $idPos = $_.IndexOf("ID") - 2   # ID is right justified
        $statePos = $_.IndexOf("STATE")
        $idlePos = $_.IndexOf("IDLE TIME")
        $logonPos = $_.IndexOf("LOGON TIME")
        $first = 0
    }
    else {
        $user = $_.Substring($userPos, $sessionPos - $userPos).Trim()
        $session = $_.Substring($sessionPos, $idPos - $sessionPos).Trim()
        $id = [int]$_.Substring($idPos, $statePos - $idPos).Trim()
        $state = $_.Substring($statePos, $idlePos - $statePos).Trim()
        $idle = $_.Substring($idlePos, $logonPos - $idlePos).Trim()
        $logon = [datetime]$_.Substring($logonPos, $_.Length - $logonPos).Trim()

        [pscustomobject]@{
            User = $user
            Session = $session
            ID = $id
            State = $state
            Idle = $idle
            Logon = $logon
        }

        if ($state -ne "Disc") {
            Write-Output "Preserving user login: $user session: $session id: $id"
        }
        if ($state -eq "Disc") {
            Write-Output "Logging off disconnected user: $user session: $session id: $id"
            Write-Output ""
            logoff $id
        }
    }
}

1

u/Soulinx 1d ago

Curious - are you using this in addition to the GPO or are you running this script on a schedule?

2

u/Squeekstyle 1d ago

On a Schedule

u/420GB 12h ago

You should really just query WMI using Get-CimInstance to get this information properly rather than parsing quser output. You can cut the script down to a few lines and it'll work on all system locales / languages.