2017-07-10 120 views
0

我編寫了一個腳本,用於改進斷開連接或空閒時間超過60分鐘的用戶。但是,我已經設置了這些參數並且過濾器工作正常。而不是斷開該服務器中的特定用戶,腳本將服務器斷開連接整個使用會話ID斷開用戶與服務器的連接

我正在使用其他兩個函數,其中一個直接添加到腳本中。另一個來自Get-LoggedOnUser.ps1Disconnect-LoggedOnUser和Get-LoggedOnUser旨在一起工作。我保留了註銷腳本的說明。我已經包含了我的完整腳本GitHub gist

非常感謝您的任何幫助或建議! 下面的所有相關代碼:

Description 
-----------  
This command dot sources the script to ensure the Disconnect-LoggedOnUser function is available in your current PowerShell session 

.EXAMPLE 
Disconnect-LoggedOnUser -ComputerName server01 -Id 5 

Description 
----------- 
Disconnect session id 5 on server01 

.EXAMPLE 
.\Get-LoggedOnUser.ps1 -ComputerName server01,server02 | Where-Object {$_.UserName -eq 'JaapBrasser'} | Disconnect-LoggedOnUser -Verbose 

<#我的腳本#>

<# 
    .SYNOPSIS 
     Convert output from CMD's 'query.exe user' to usable objects. 

    .DESCRIPTION 
     Take the text based output returned by 'query.exe user' and convert it to objects that can be manipulated in PowerShell. 

    .PARAMETER Name 
     Computer name to run query.exe against. 

    .EXAMPLE 
     PS C:\> Convert-QueryToObjects -Name server01 
     ComputerName Username SessionState SessionType 
     ------------ -------- ------------ ----------- 
     server01  bobsmith Disconnected 
     server01  janedoe Active  tcp-rdp 
#> 


function Disconnect-LoggedOnUser { 
<# 
.SYNOPSIS 
Function to disconnect a RDP session remotely 

.DESCRIPTION 
This function provides the functionality to disconnect a RDP session remotely by providing the ComputerName and the SessionId 

.PARAMETER ComputerName 
This can be a single computername or an array where the RDP sessions will be disconnected 

.PARAMETER Id 
The Session Id that that will be disconnected 

.NOTES 
Name: Disconnect-LoggedOnUser 
Author: Jaap Brasser 
DateUpdated: 2015-06-03 
Version: 1.0 
Blog: http://www.jaapbrasser.com 

.LINK 
http://www.jaapbrasser.com 

.EXAMPLE 
. .\Disconnect-LoggedOnUser.ps1 

Description 
-----------  
This command dot sources the script to ensure the Disconnect-LoggedOnUser function is available in your current PowerShell session 

.EXAMPLE 
Disconnect-LoggedOnUser -ComputerName server01 -Id 5 

Description 
----------- 
Disconnect session id 5 on server01 

.EXAMPLE 
.\Get-LoggedOnUser.ps1 -ComputerName server01,server02 | Where-Object {$_.UserName -eq 'JaapBrasser'} | Disconnect-LoggedOnUser -Verbose 

Description 
----------- 
Use the Get-LoggedOnUser script to gather the user sessions on server01 and server02. Where-Object filters out only the JaapBrasser user account and then disconnects the session by piping the results into Disconnect-LoggedOnUser while displaying verbose information. 
#> 
    param(
     [Parameter(
      Mandatory, 
      ValueFromPipeline, 
      ValueFromPipelineByPropertyName, 
      Position=0 
     )] 
     [string[]] 
      $ComputerName, 
     [Parameter(
      Mandatory, 
      ValueFromPipelineByPropertyName 
     )] 
     [int[]] 
      $Id 
    ) 

    begin { 
     $OldEAP = $ErrorActionPreference 
     $ErrorActionPreference = 'Stop' 
    } 

    process { 
     foreach ($Computer in $ComputerName) { 
      $Id | ForEach-Object { 
       Write-Verbose "Attempting to disconnect session $Id on $Computer" 
       try { 
        rwinsta $_ /server:$Computer 
        Write-Verbose "Session $Id on $Computer successfully disconnected" 
       } catch { 
        Write-Verbose 'Error disconnecting session displaying message' 
        Write-Warning "Error on $Computer, $($_.Exception.Message)" 
       } 
      } 
     } 
    } 

    end { 
     $ErrorActionPreference = $OldEAP 
    } 
} 






function Convert-QueryToObjects 
{ 
    [CmdletBinding()] 
    [Alias('QueryToObject')] 
    [OutputType([PSCustomObject])] 
    param 
    (
     [Parameter(Mandatory = $false, 
        ValueFromPipeline = $true, 
        ValueFromPipelineByPropertyName = $true, 
        Position = 0)] 
     [Alias('ComputerName', 'Computer')] 
     [string] 
     $Name = $env:COMPUTERNAME 
    ) 

    Process 
    { 
     Write-Verbose "Running query.exe against $Name." 
     $Users = query user /server:$Name 2>&1 

     if ($Users -like "*No User exists*") 
     { 
      # Handle no user's found returned from query. 
      # Returned: 'No User exists for *' 
      Write-Error "There were no users found on $Name : $Users" 
      Write-Verbose "There were no users found on $Name." 
     } 
     elseif ($Users -like "*Error*") 
     { 
      # Handle errored returned by query. 
      # Returned: 'Error ...<message>...' 
      Write-Error "There was an error running query against $Name : $Users" 
      Write-Verbose "There was an error running query against $Name." 
     } 
     elseif ($Users -eq $null -and $ErrorActionPreference -eq 'SilentlyContinue') 
     { 
      # Handdle null output called by -ErrorAction. 
      Write-Verbose "Error action has supressed output from query.exe. Results were null." 
     } 
     else 
     { 
      Write-Verbose "Users found on $Name. Converting output from text." 

      # Conversion logic. Handles the fact that the sessionname column may be populated or not. 
      $Users = $Users | ForEach-Object { 
       (($_.trim() -replace ">" -replace "(?m)^([A-Za-z0-9]{3,})\s+(\d{1,2}\s+\w+)", '$1 none $2' -replace "\s{2,}", "," -replace "none", $null)) 
      } | ConvertFrom-Csv 

      Write-Verbose "Generating output for $($Users.Count) users connected to $Name." 

      # Output objects. 
      foreach ($User in $Users) 
      { 
       Write-Verbose $User 
       if ($VerbosePreference -eq 'Continue') 
       { 
        # Add '| Out-Host' if -Verbose is tripped. 
        [PSCustomObject]@{ 
         ComputerName = $Name 
         Username = $User.USERNAME 
         SessionState = $User.STATE.Replace("Disc", "Disconnected") 
         SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "") 
         IdleTime = $User.'IDLE TIME' 
         ID = $User.ID 
         LogonTime =$User.'Logon Time' 
        } | Out-Host 
       } 
       else 
       { 
        # Standard output. 
        [PSCustomObject]@{ 
         ComputerName = $Name 
         Username = $User.USERNAME 
         SessionState = $User.STATE.Replace("Disc", "Disconnected") 
         SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "") 
         IdleTime = $User.'IDLE TIME' 
         LogonTime = $User.'Logon Time' 
         ID = $User.ID 
        } 
       } 
      } 
     } 
    } 
} 


$Servers = Get-Content 'H:\demo\computernames.txt' 
$Queries = foreach ($Server in $Servers) { 
    #Query each server that pings, save it in a variable for reuse 
    if (Test-Connection $Server -Count 1 -Quiet) { 
     Convert-QueryToObjects $Server -ErrorAction SilentlyContinue 
    } 
} 

#Open servers are ones that responded to the query. 
$Queries | 
    Select-Object -ExpandProperty ComputerName -Unique | 
    Out-File 'H:\demo\session\openservers.txt' 

#Use the saved query information, filter with Where-Object, loop over to disconnect. 
$Queries | 
    Where-Object { ($_.SessionState -eq 'Disconnected') -or (($_.IdleTime -like "*:*") -and ($_.IdleTime -gt "00:59"))} | 
    ForEach-Object { 
     Disconnect-LoggedOnUser -ComputerName $_.ComputerName -Id $_.ID -Verbose 
    } 
+2

它完全按照你所說的去做。 'H:\ WindowsPowerShell \ Get-LoggedOnUser.ps1 -ComputerName $ Server | Disconnect-LoggedOnUser -Verbose'根本不用'Where-Object'進行過濾。所以會斷開一切。 – BenH

+0

@BenH我想說的是,我嘗試添加'Where-Object {$ _。ID -eq'$ Id'}'',但似乎沒有解決問題。我接近錯了嗎?謝謝 – russell

+1

使用單引號不允許評估變量。但是,這隻能解決一件事,另一件是你從哪裏獲得'$ ID'。 – BenH

回答

2

問題是H:\WindowsPowerShell\Get-LoggedOnUser.ps1 -ComputerName $Server| Disconnect-LoggedOnUser -Verbose不與Where-Object過濾。因此,您需要保存哪些用戶會話需要斷開連接的信息,然後使用過濾的信息斷開連接。

這裏有一種方法來處理它,內聯評論。

$Servers = Get-Content 'H:\demo\computernames.txt' 
$Queries = foreach ($Server in $Servers) { 
    #Query each server that pings, save it in a variable for reuse 
    if (Test-Connection $Server -Count 1 -Quiet) { 
     Convert-QueryToObjects $Server -ErrorAction SilentlyContinue 
    } 
} 

#Open servers are ones that responded to the query. 
$Queries | 
    Select-Object -ExpandProperty ComputerName -Unique | 
    Out-File 'H:\demo\session\openservers.txt' 

#Use the saved query information, filter with Where-Object, loop over to disconnect. 
$Queries | 
    Where-Object { ($_.SessionState -eq 'Disconnected') -or (($_.IdleTime -like "*:*") -and ($_.IdleTime -gt "00:59"))} | 
    ForEachObject { 
     Disconnect-LoggedOnUser -ComputerName $_.ComputerName -Id $_.ID -Verbose 
    } 
+0

謝謝你,但我已經將你的腳本添加到了我的程序中;它似乎並沒有通過所有的服務器進行連接,而只是針對其中一個服務器(最後一個服務器)爲我所描述的代碼完全粘貼。我已經更新了我的代碼在github gist [找到](https://gist.github.com/ruslive109/59673e6785230d156d5f6a4d0134152b)謝謝 – russell

+0

@russell道歉,我的代碼保存在'$ Queries'每個循環的$ Server'。我已更新我的答案,以解決問題 – BenH

+0

再次感謝您!無論如何,我還可以像以前一樣列出變量嗎?而不僅僅是斷開狀態。謝謝 – russell

相關問題