Tôi gặp vấn đề này với người dùng ứng dụng Remote Desktop bị khóa. Tôi đã viết tập lệnh Powershell này để chạy trên một tác vụ theo lịch trình để đăng xuất người dùng hiển thị bị ngắt kết nối trong hơn 2 phút. Chỉnh sửa duy nhất được yêu cầu là SERVERNAME mà tôi đã đặt để loại trừ Máy chủ môi giới máy tính từ xa, tuy nhiên bạn có thể loại trừ bất kỳ máy chủ nào bạn thích hoặc không có máy chủ nào cả.
Nhân tiện, kịch bản của tôi đã được viết cho Windows Server 2012 R2, nhân tiện ...
Kịch bản thực hiện điều này:
- Nhận danh sách tất cả các phiên người dùng máy tính từ xa.
- Bỏ qua mọi phiên không nói "STATE_DISCONNECTED".
- Bỏ qua Máy chủ môi giới (hoặc bất kỳ máy chủ nào khác)
- Bỏ qua mọi phiên không có Id phiên hợp nhất
- Bỏ qua bất kỳ phiên nào không có thời gian ngắt kết nối
- Đối với những phiên có thời gian ngắt kết nối, nó sẽ kiểm tra thời gian hiện tại và nếu chênh lệch thời gian giữa giờ và thời gian ngắt kết nối là hơn X phút (trong trường hợp này là 2), sẽ giết quá trình winlogon.
- Nó cũng cố gắng đưa ra một lệnh đăng xuất (Điều này rất có thể sẽ thất bại sau khi quá trình winlogon bị giết).
Nó làm việc cho tôi! Tôi hy vọng nó sẽ giúp người khác! :)
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'
}
}
}
Hoặc nếu bạn thích một phiên bản mà bạn có thể thấy những gì đang diễn ra trên màn hình:
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"
}
}
}