[英]Powershell Log Off Remote Session
我正在嘗試制定一個 Powershell 命令來遠程注銷用戶。 我們有一個終端服務器,其程序非常不穩定,有時會鎖定會話。 我們必須遠程注銷用戶,但我正在嘗試編寫一個 Powershell 語句來注銷運行腳本的人。 我用 Google 搜索了一下,發現了這個命令:
Invoke-Command -ComputerName MyServer -Command {shutdown -l}
但是,該命令返回“不正確的 function”。 我可以成功運行括號中的其他命令,例如Get-Process。
我的想法是將其放入用戶可以運行的腳本中以從服務器注銷(因為當它鎖定時,他們無法訪問開始菜單或 ALT+CTRL+END 以通過 GUI 執行此操作)。
流程是這樣的:Bob 通過 RDP 登錄到 MyServer,但他的 session 凍結了。 在他的本地桌面上,他可以運行 MyScript(包含與上面類似的命令),這將在 MyServer 上注銷他的 session。
也許令人驚訝的是,您可以使用logoff
命令注銷用戶。
C:\> logoff /?
Terminates a session.
LOGOFF [sessionname | sessionid] [/SERVER:servername] [/V] [/VM]
sessionname The name of the session.
sessionid The ID of the session.
/SERVER:servername Specifies the Remote Desktop server containing the user
session to log off (default is current).
/V Displays information about the actions performed.
/VM Logs off a session on server or within virtual machine.
The unique ID of the session needs to be specified.
會話 ID 可以使用qwinsta
( query session
)或quser
( query user
)命令確定(請參閱此處):
$server = 'MyServer'
$username = $env:USERNAME
$session = ((quser /server:$server | ? { $_ -match $username }) -split ' +')[2]
logoff $session /server:$server
添加普通的 DOS 命令,如果有人願意的話。 是的,這仍然適用於 Win 8 和 Server 2008 + Server 2012。
Query session /server:Server100
將返回:
SESSIONNAME USERNAME ID STATE TYPE DEVICE
rdp-tcp#0 Bob 3 Active rdpwd
rdp-tcp#5 Jim 9 Active rdpwd
rdp-tcp 65536 Listen
要注銷會話,請使用:
Reset session 3 /server:Server100
這是一個很棒的腳本解決方案,用於遠程或本地注銷人員。 我正在使用 qwinsta 來獲取會話信息並從給定的輸出中構建一個數組。 這使得遍歷每個條目並僅注銷實際用戶而不是系統或 RDP 偵聽器本身非常容易,后者通常只會拋出訪問拒絕錯誤。
$serverName = "Name of server here OR localhost"
$sessions = qwinsta /server $serverName| ?{ $_ -notmatch '^ SESSIONNAME' } | %{
$item = "" | Select "Active", "SessionName", "Username", "Id", "State", "Type", "Device"
$item.Active = $_.Substring(0,1) -match '>'
$item.SessionName = $_.Substring(1,18).Trim()
$item.Username = $_.Substring(19,20).Trim()
$item.Id = $_.Substring(39,9).Trim()
$item.State = $_.Substring(48,8).Trim()
$item.Type = $_.Substring(56,12).Trim()
$item.Device = $_.Substring(68).Trim()
$item
}
foreach ($session in $sessions){
if ($session.Username -ne "" -or $session.Username.Length -gt 1){
logoff /server $serverName $session.Id
}
}
在此腳本的第一行中,如果在本地運行,則為 $serverName 提供適當的值或 localhost。 我使用此腳本在自動過程嘗試移動某些文件夾之前踢用戶。 為我防止“文件正在使用”錯誤。 另一個注意事項,此腳本必須以管理員用戶身份運行,否則您可能會在嘗試注銷某人時被拒絕訪問。 希望這可以幫助!
這是老式的並且早於 PowerShell,但我多年來一直使用 qwinsta / rwinsta 組合來遠程注銷過時的 RDP 會話。 它至少內置於 Windows XP 及更高版本(可能更早)
確定會話 ID:
qwinsta /SERVER:<NAME>
刪除有問題的會話:
rwinsta <SESSION_ID> /SERVER:<NAME>
您可以使用Invoke-RDUserLogoff
注銷特定組織單位的 Active Directory 用戶的示例:
$users = Get-ADUser -filter * -SearchBase "ou=YOUR_OU_NAME,dc=contoso,dc=com"
Get-RDUserSession | where { $users.sAMAccountName -contains $_.UserName } | % { $_ | Invoke-RDUserLogoff -Force }
在管道的末尾,如果您嘗試僅使用 foreach (%),它將僅注銷一個用戶。 但是使用這種 foreach 和 pipe 的組合:
| % { $_ | 命令 }
將按預期工作。
附言。 以管理員身份運行。
Get-TSSession -ComputerName comp1 -UserName user1 | Stop-TSSession -Force
我通過執行以下操作將Casey 的回答修改為僅注銷斷開連接的會話:
foreach($Server in $Servers) {
try {
query user /server:$Server 2>&1 | select -skip 1 | ? {($_ -split "\s+")[-5] -eq 'Disc'} | % {logoff ($_ -split "\s+")[-6] /server:$Server /V}
}
catch {}
}
從一台機器注銷所有用戶:
try {
query user /server:$SERVER 2>&1 | select -skip 1 | foreach {
logoff ($_ -split "\s+")[-6] /server:$SERVER
}
}
catch {}
細節:
try
/ catch
,並且query
返回錯誤。 但是,如果您不介意看到錯誤字符串,您可以刪除2>&1
部分,並刪除try
/ catch
select -skip 1
刪除標題行foreach
注銷每個用戶($_ -split "\\s+")
將字符串拆分為僅包含文本項的數組[-6]
index 獲取會話 ID 並且是從數組的反向計數的第 6 個字符串,您需要這樣做,因為query
輸出將有 8 或 9 個元素,具體取決於用戶是否連接到終端會話或從終端會話斷開我相信我的代碼會更容易並且運行得更快。
$logon_sessions = get-process -includeusername | Select-Object -Unique -Property UserName, si | ? { $_ -match "server" -and $_ -notmatch "admin" }
foreach ($id in $logon_sessions.si) {
logoff $id
}
由於我們位於PowerShell區域,因此如果我們可以返回正確的PowerShell對象,則它特別有用...
我個人喜歡這種解析方法,因為簡潔:
((quser) -replace '^>', '') -replace '\s{2,}', ',' | ConvertFrom-Csv
注意: 這不能解決未連接(“ disc”)用戶的問題,但是如果您只想快速獲得用戶列表而不關心其余信息,則效果很好。 我只想要一個列表,並不關心它們當前是否斷開連接。
如果您確實關心其余數據,則只會稍微復雜一點:
(((quser) -replace '^>', '') -replace '\s{2,}', ',').Trim() | ForEach-Object {
if ($_.Split(',').Count -eq 5) {
Write-Output ($_ -replace '(^[^,]+)', '$1,')
} else {
Write-Output $_
}
} | ConvertFrom-Csv
只要用戶有權遠程運行注銷命令,下面的腳本將適用於活動會話和斷開連接的會話。 您所要做的就是從第 4 行的“YourServerName”更改服務器名稱。
param (
$queryResults = $null,
[string]$UserName = $env:USERNAME,
[string]$ServerName = "YourServerName"
)
if (Test-Connection $ServerName -Count 1 -Quiet) {
Write-Host "`n`n`n$ServerName is online!" -BackgroundColor Green -ForegroundColor Black
Write-Host ("`nQuerying Server: `"$ServerName`" for disconnected sessions under UserName: `"" + $UserName.ToUpper() + "`"...") -BackgroundColor Gray -ForegroundColor Black
query user $UserName /server:$ServerName 2>&1 | foreach {
if ($_ -match "Active") {
Write-Host "Active Sessions"
$queryResults = ("`n$ServerName," + (($_.trim() -replace ' {2,}', ','))) | ConvertFrom-Csv -Delimiter "," -Header "ServerName","UserName","SessionName","SessionID","CurrentState","IdealTime","LogonTime"
$queryResults | ft
Write-Host "Starting logoff procedure..." -BackgroundColor Gray -ForegroundColor Black
$queryResults | foreach {
$Sessionl = $_.SessionID
$Serverl = $_.ServerName
Write-Host "Logging off"$_.username"from $serverl..." -ForegroundColor black -BackgroundColor Gray
sleep 2
logoff $Sessionl /server:$Serverl /v
}
}
elseif ($_ -match "Disc") {
Write-Host "Disconnected Sessions"
$queryResults = ("`n$ServerName," + (($_.trim() -replace ' {2,}', ','))) | ConvertFrom-Csv -Delimiter "," -Header "ServerName","UserName","SessionID","CurrentState","IdealTime","LogonTime"
$queryResults | ft
Write-Host "Starting logoff procedure..." -BackgroundColor Gray -ForegroundColor Black
$queryResults | foreach {
$Sessionl = $_.SessionID
$Serverl = $_.ServerName
Write-Host "Logging off"$_.username"from $serverl..."
sleep 2
logoff $Sessionl /server:$Serverl /v
}
}
elseif ($_ -match "The RPC server is unavailable") {
Write-Host "Unable to query the $ServerName, check for firewall settings on $ServerName!" -ForegroundColor White -BackgroundColor Red
}
elseif ($_ -match "No User exists for") {Write-Host "No user session exists"}
}
}
else {
Write-Host "`n`n`n$ServerName is Offline!" -BackgroundColor red -ForegroundColor white
Write-Host "Error: Unable to connect to $ServerName!" -BackgroundColor red -ForegroundColor white
Write-Host "Either the $ServerName is down or check for firewall settings on server $ServerName!" -BackgroundColor Yellow -ForegroundColor black
}
Read-Host "`n`nScript execution finished, press enter to exit!"
如果沒有找到會話: 也請查看此解決方案以查詢所有 AD 服務器以獲取您的用戶名並僅注銷斷開連接的會話。 該腳本還會告訴您連接或查詢服務器是否出錯。
這是我想出的。 結合多個答案
#computer list below
$computers = (
'computer1.domain.local',
'computer2.domain.local'
)
foreach ($Computer in $computers) {
Invoke-Command -ComputerName $Computer -ScriptBlock {
Write-Host '______ '$Env:Computername
$usertocheck = 'SomeUserName'
$sessionID = ((quser | Where-Object { $_ -match $usertocheck }) -split ' +')[2]
If([string]::IsNullOrEmpty($sessionID)){
Write-Host -ForegroundColor Yellow "User Not Found."
} else {
write-host -ForegroundColor Green 'Logging off ' $usertocheck 'Session ID' $sessionID
logoff $sessionID
}
}
}
下面的簡單腳本將注銷同一台計算機上所有斷開連接的用戶
$hostname = hostname
if (Test-Connection -ComputerName $hostname -Quiet -Count 1){
$result = query session /server:$hostname
$rows = $result -split "`n"
foreach ($row in $rows) {
if ($row -NotMatch "services|console" -and $row -match "Disc") {
$sessionusername = $row.Substring(19,20).Trim()
$sessionid = $row.Substring(39,9).Trim()
Write-Output "Logging Off RDP Disconnected Sessions User $sessionusername"#, $session[2], $session[3]"
logoff $sessionid /server:$hostname
}
}
}
Output 會
Logging Off RDP Disconnected Sessions User xyz
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.