簡體   English   中英

Powershell 注銷遠程 Session

[英]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 可以使用qwinstaquery session )或quserquery 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 的組合:

| % { $_ | 命令 }

將按預期工作。

附言。 以管理員身份運行。

嘗試終端服務 PowerShell 模塊

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 服務器以獲取您的用戶名並僅注銷斷開連接的會話。 該腳本還會告訴您連接或查詢服務器是否出錯。

Powershell 找出斷開的 RDP 會話並同時注銷

這是我想出的。 結合多個答案

#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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM