2017-07-10 54 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

相关问题