使用Powershell查找已断开的RDP会话并同时注销

4
有没有一种脚本可以注销我在任何服务器上的断开的RDP会话?这导致了很多麻烦和不断的广告帐户锁定。
任何帮助都将是非常棒的。
2个回答

9
我已经得到了答案,并写下这个答案来帮助需要帮助的人,因为我不得不自己解决这个问题。我使用在线资源创建了一个脚本,以查找我AD环境中所有Windows Server上的断开连接的RDP会话。我在每台Windows Server上运行一个查询并创建一个CSV格式的列表,然后使用该列表从这些服务器上注销我的ID,以便我没有任何断开的会话。
我这样做是为了确保在更改密码时,我的AD帐户不会由于某些断开的RDP会话而被锁定。
你可以根据你的需求自由修改这个脚本。
脚本代码如下:
param (
        #get current logged on username
        [string]$UserName = $env:USERNAME
    )

    # Import the Active Directory module for the Get-ADComputer CmdLet
    Import-Module ActiveDirectory


    # Query Active Directory for enabled windows servers computer accounts and sort by name
    $Servers = Get-ADComputer -Filter {(OperatingSystem -like "*windows*server*") -and (Enabled -eq "True")} | Sort Name

    # Initiating variables
    $SessionList = $NULL
    $queryResults = $NULL
    $SError = $null
    $SDown = $null
    $z = 0

    # Get total number of servers
    $count = $Servers.count 


    # Start looping through each server at a time
    ForEach ($Server in $Servers) {    

        # initiate counter for showing progress
        $z = $z + 1

        $ServerName = $Server.Name

        # Start writing progress 
        Write-Progress -Activity "Processing Server: $z out of $count servers." -Status " Progress" -PercentComplete ($z/$Servers.count*100)

        # check if server is pingable before running the query on the server
        if (Test-Connection $Server.Name -Count 1 -Quiet) {  

            Write-Host "`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

            # Store results in array
            [array]$queryResults += (

                # Query server for specific username
                query user $UserName /server:$ServerName | 
                foreach {
                    # Look for lines with Disc string to filter out active sessions
                    if ($_ -match "Disc") {

                        # format the output in CSV by replacing more than 2 spaces with a comman
                        write-output ("`n$ServerName," + (($_.trim() -replace ' {2,}', ',')))
                    }
                }
            )
        }
        # If server is not pingable show error message
        else {
            # Make list of server that are down.
            [array]$SDown += ($ServerName)
            Write-Host "`nError: 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
        }
    }

    # If there are some non pingable server then display the list
    if ($SDown -ne $null -and $SDown) {
            Write-Host "`nScript was unable to connect to the following server:" -ForegroundColor White -BackgroundColor Red
            $SDown
    }

    # Check if any disconnected session are stored in the array
    if ($queryResults -ne $null -and $queryResults) {

        # Convert the CSV fromat to table format with headers
        $QueryResultsCSV = $queryResults | ConvertFrom-Csv -Delimiter "," -Header "ServerName","UserName","SessionID","CurrentState","IdealTime","LogonTime"

        # Show the results on console
        $QueryResultsCSV |ft -AutoSize

        # Go through each Disconnected session stored in the array
        $QueryResultsCSV | foreach {

            # Grabb session ID and ServerName
            $Sessionl = $_.SessionID
            $Serverl = $_.ServerName

            # Show message on the console
            Write-Host "`nLogging off"$_.username"from $serverl..." -ForegroundColor black -BackgroundColor Gray
            sleep 2

            # Logout user using session ID
            logoff $Sessionl /server:$Serverl /v

        }
    }
    else {
        # if array is empty display message that no session were found
        Write-Host `n`n`n`n("*" * $LineSize)
        Write-Host "You are all good! No ghost sessions found!" -BackgroundColor Green -ForegroundColor Black
        Write-Host ("*" * $LineSize)
    }

    # Pause at the end so you can capture the output
    $null = Read-Host "`n`nScript execution finished, press enter to exit!"

截图:

  1. 当脚本在所有服务器上运行时,会显示在线和离线服务器: 初始脚本运行

  2. 无法连接的服务器列表: 脚本无法连接的服务器列表

  3. 脚本列出了发现断开的RDP会话的服务器。 已断开的RDP会话

  4. 当脚本开始注销您的断开会话并在结束时暂停。 输入图像描述


我知道栈不喜欢感谢评论,但我想让您知道这个脚本太棒了。它使我的生活轻松了1,000,000倍。谢谢! - user4669250
1
@Bridger 很高兴能帮忙。 :) - LT-
写得很好,PSTerminalServices更符合PowerShell本地化。 - Nixphoe
1
@Nixphoe,如果我没记错的话,PSTerminalServices出来之前我写了我的脚本两年了。 - LT-
如何让这个搜索不是以我的身份进行,而是以另一个用户的身份进行?每次我用要搜索的用户名替换掉"$username"时,它仍然会将我的用户名添加到搜索中。 - Rich M

0

感谢您提供的示例代码。我已经编写了一个简化的代码,用于注销同一服务器上的所有断开连接的用户。

$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
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接