ฉันมีปัญหานี้กับผู้ใช้แอปพลิเคชันเดสก์ท็อประยะไกลที่ล็อคไว้ ฉันเขียนสคริปต์ Powershell นี้เพื่อทำงานตามกำหนดเวลาเพื่อออกจากระบบผู้ใช้ที่แสดงว่าไม่ได้เชื่อมต่อนานกว่า 2 นาที การแก้ไขที่จำเป็นเท่านั้นคือSERVERNAMEที่ฉันตั้งค่าให้ยกเว้นเซิร์ฟเวอร์ Broker ของเดสก์ท็อประยะไกลอย่างไรก็ตามคุณสามารถยกเว้นเซิร์ฟเวอร์ที่คุณต้องการหรือไม่ต้องการเลยก็ได้
สคริปต์ของฉันเขียนขึ้นสำหรับ Windows Server 2012 R2 โดยวิธี ...
สคริปต์ทำสิ่งนี้:
- รับรายการเซสชันผู้ใช้เดสก์ท็อประยะไกลทั้งหมด
- ละเว้นเซสชันใด ๆ ที่ไม่ได้พูดว่า "STATE_DISCONNECTED"
- ละเว้นเซิร์ฟเวอร์โบรคเกอร์ (หรือเซิร์ฟเวอร์อื่น ๆ )
- ละเว้นเซสชันใด ๆ ที่ไม่มีรหัสเซสชันแบบรวม
- ละเว้นเซสชันใด ๆ ที่ไม่มีเวลาตัดการเชื่อมต่อ
- สำหรับเซสชันที่มีเวลาตัดการเชื่อมต่อจะตรวจสอบเวลาปัจจุบันและหากความแตกต่างของเวลาระหว่างตอนนี้และเวลาตัดการเชื่อมต่อมากกว่า X นาที (ในกรณีนี้ 2) จะฆ่ากระบวนการ winlogon
- นอกจากนี้ยังพยายามที่จะออกคำสั่งออกจากระบบ (ซึ่งมักจะล้มเหลวหลังจากกระบวนการ winlogon ถูกฆ่าตาย)
มันใช้งานได้สำหรับฉัน! ฉันหวังว่ามันจะช่วยคนอื่น! :)
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'
}
}
}
หรือหากคุณต้องการรุ่นที่คุณสามารถเห็นสิ่งที่เกิดขึ้นบนหน้าจอ:
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"
}
}
}