Saya mengalami masalah ini dengan pengguna Aplikasi Desktop Jarak Jauh yang terkunci. Saya menulis skrip Powershell ini untuk dijalankan pada tugas yang dijadwalkan untuk keluar dari pengguna yang menunjukkan terputus selama lebih dari 2 menit. Satu-satunya pengeditan yang diperlukan adalah SERVERNAME yang saya setel untuk mengecualikan Server Desktop Pialang Jarak Jauh, namun Anda dapat mengecualikan server apa pun yang Anda suka, atau tidak sama sekali.
Skrip saya ditulis untuk Windows Server 2012 R2, omong-omong ...
Script melakukan ini:
- Mendapat daftar semua Sesi Pengguna Desktop Jarak Jauh.
- Abaikan sesi apa pun yang tidak mengatakan "STATE_DISCONNECTED".
- Abaikan Server Broker (atau server lain)
- Abaikan sesi apa pun tanpa ID Sesi Terpadu
- Abaikan sesi apa pun yang tidak memiliki waktu pemutusan
- Untuk sesi yang memiliki waktu pemutusan, ia memeriksa waktu saat ini dan jika perbedaan waktu antara sekarang dan waktu pemutusan lebih dari X menit (dalam kasus ini 2), membunuh proses winlogon.
- Itu juga mencoba untuk mengeluarkan perintah log off (Ini kemungkinan besar akan gagal setelah proses winlogon terbunuh).
Ini bekerja untuk saya! Saya harap ini membantu orang lain! :)
CLS
$RD = Get-RDUserSession | select ServerName, UserName, SessionState, DisconnectTime, UnifiedSessionId, SessionId #Get details about the sessions
foreach ($item in $RD) {
$UsessionID = $item.UnifiedSessionId -as [int]
$sessionID = $item.SessionId -as [int]
if ($item.SessionState -eq "STATE_DISCONNECTED" -and $item.ServerName -ne "SERVERNAME" -and $item.DisconnectTime -ne $null -and $item.UnifiedSessionId -ne $null){
$TimeDiff = New-TimeSpan -start $item.DisconnectTime -end (Get-Date) #check time difference between disconnect time and now. If time is greater than 2 minutes....
if ($TimeDiff.Minutes -gt 2) {
#Kill winlogon session for the user
Get-WmiObject -ComputerName $item.Servername -query "select * from win32_process where name='winlogon.exe'" | Where-Object {$_.SessionId -eq $SessionId} | %{$_.terminate()}
#Log off user if session still exists (will fail if user kicked)
Invoke-RDUserLogoff -HostServer $item.ServerName -UnifiedSessionID $UsessionID -Force -erroraction 'silentlycontinue'
}
}
}
Atau jika Anda lebih suka versi yang dapat Anda lihat apa yang terjadi di layar:
CLS
$RD = Get-RDUserSession | select ServerName, UserName, SessionState, DisconnectTime, UnifiedSessionId, SessionId
foreach ($item in $RD) {
$UsessionID = $item.UnifiedSessionId -as [int]
$sessionID = $item.SessionId -as [int]
if ($item.SessionState -eq "STATE_DISCONNECTED" -and $item.ServerName -ne "SERVERNAME" -and $item.DisconnectTime -ne $null -and $item.UnifiedSessionId -ne $null){
#On Screen Output
write-host " Name : " $Item.UserName -ForegroundColor "yellow" -NoNewline
write-host " Unified Session Id : " $UsessionID -ForegroundColor "darkcyan" -NoNewline
write-host " User Session Id : " $sessionID -ForegroundColor "darkyellow" -NoNewline
write-host " Session State : " $item.SessionState -ForegroundColor "magenta" -NoNewline
write-host " Server : " $item.ServerName -ForegroundColor "cyan" -NoNewline
write-host " Disconnect Time : " $item.DisconnectTime -ForegroundColor "gray"
#End On Screen Output
$TimeDiff = New-TimeSpan -start $item.DisconnectTime -end (Get-Date)
if ($TimeDiff.Minutes -lt 2) {
write-host " Disconnected for less than 2 minutes" -ForegroundColor "Green"}
else {
write-host " Disconnected for more than 2 minutes" -ForegroundColor "Red" -BackgroundColor "darkyellow"
write-host " Killing session : " $item.ServerName " ID : " $UsessionID $item.UserName -ForegroundColor "Red"
#Kill Process "Winlogon.exe" for the user (this should kill the session)
Get-WmiObject -ComputerName $item.Servername -query "select * from win32_process where name='winlogon.exe'" | Where-Object {$_.SessionId -eq $SessionId} | %{$_.terminate()}
#Logout User (if session still exists)
Invoke-RDUserLogoff -HostServer $item.ServerName -UnifiedSessionID $UsessionID -Force -erroraction 'silentlycontinue'
Write-host " Done! " -ForegroundColor "Green" -BackgroundColor "blue"
}
}
}