How to end disconnected RDP sessions with PowerShell
The PowerShell script below logs off a disconnected session if the session has been idle for XX minutes, and it also excludes specific users. Additionally, the script writes a log file that includes the memory usage of the session.
# Define the list of users to exclude from logoff
$excludedUsers = @("user1", "user2","user3")
# Define the maximum allowed idle time (in minutes). Minimum 60 minutes
$maxIdleMinutes = 2880
###########################################################################
# Get the list of RDP sessions
$rdpSessions = quser
# Iterate through the RDP sessions and log off users not in the excluded list
foreach ($session in $rdpSessions) {
$sessionInfo = $session -split "\s+"
$username = $sessionInfo[0]
$sessionId = $sessionInfo[2]
$Username = $session.SubString(1, 20).Trim()
$SessionName = $session.SubString(23, 17).Trim()
$ID = $session.SubString(42, 2).Trim()
$State = $session.SubString(46, 6).Trim()
$Idle = $session.SubString(54, 9).Trim().Replace('+', ':')
# skip disconnected, skip certain users, skip session ids with id 0
if ($excludedUsers -notcontains $username -and $sessionId -ne "0" -and $state -eq "Disc" ) {
$timeParts="0"
write-output "* $($username)"
# Input time duration in the format "dd:hh:mm", "hh:mm", or "mm"
$timeDuration = $idle
$timeParts = $timeDuration -split ":"
$days = 0
$hours = 0
$minutes = 0
$totalMinutes = 0
# Check the number of time parts and assign values accordingly
if ($timeParts.Count -eq 3) {
$days, $hours, $minutes = $timeParts
} elseif ($timeParts.Count -eq 2) {
$hours, $minutes = $timeParts
} elseif ($timeParts.Count -eq 1) {
$minutes = $timeParts
}
#0 would give errors during calculation, and should be excluded
if($minutes -ne "0" -and $hours -ne "0" -and $minutes -ne "0" ) {
$totalMinutes = [math]::Round(([int]::Parse($days) * 1440) + ([int]::Parse($hours) * 60) + [int]::Parse($minutes))
Write-output " Idle: $($totalMinutes) minutes"
$sessionProcesses = Get-WmiObject Win32_Process -Filter "SessionId = $($sessionid)"
$totalMemoryUsage = 0
# Iterate through the processes and calculate the total memory usage
foreach ($process in $sessionProcesses) {
$totalMemoryUsage += $process.WorkingSetSize
}
# Convert the total memory usage to megabytes (MB)
$totalMemoryUsageMB = [math]::Round($totalMemoryUsage / 1MB, 2)
# Output the total memory usage for the session
if ($totalMinutes -ge $maxIdleMinutes -and $totalMinutes -ne "0") {
write-output " ** Killing session for $($username) : $($sessionid)"
Write-Host " Total Memory Usage: $(${totalMemoryUsageMB})MB"
Add-Content c:\support\end_disconnected_sessions.log "$(get-date) : Killing session for $($username) : $($sessionid) , idle time: $($totalMinutes) minutes , Total Memory Usage: $(${totalMemoryUsageMB})MB"
Logoff $sessionId
} else {
write-output " ** NOT Killing session for $($username) : $($sessionid)"
Write-Host " Total Memory Usage: $(${totalMemoryUsageMB})MB"
Add-Content c:\support\end_disconnected_sessions.log "$(get-date) : Not killing disconnected session for $($username) : $($sessionid) , idle time: $($totalMinutes) minutes , Total Memory Usage: $(${totalMemoryUsageMB})MB"
}
}
}
}