ForEach-Object循环问题

时间:2017-07-12 12:24:21

标签: powershell csv

我遇到了多次运行同一服务器会话的ForEach-Object属性的问题。但是,列表上的服务器会话只运行一次。我认为这是循环的一个问题。

if (Test-Path 'H:\demo\session\run11.csv') {
    Clear-Content 'H:\demo\session\run11.csv'
}

$Servers = Get-Content 'H:\demo\computernames.txt'
$openservers = @()

foreach ($Server in $Servers) {
    if (-not (Test-Connection $Server -Count 1 -Quiet)) { continue }

    if (-not (Convert-QueryToObjects $Server -ErrorAction SilentlyContinue)) {
        $openservers += $server
        $openservers | Out-File 'H:\demo\session\openservers.txt'
    } else {  
        Convert-QueryToObjects -Name $Server | Where-Object {
            @('Disconnected','Active') -contains $_.SessionState
        } | Export-Csv H:\demo\session\run11.csv -NoTypeInformation -Append 
    }
}

function Disconnect-LoggedOnUser {
    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
    }
}

Import-Csv 'H:\demo\session\run11.csv' | Where-Object {
    ($_.SessionState -eq 'Disconnected') -or
    (($_.IdleTime -like "*:*") -and ($_.IdleTime -gt "00:59"))
} | ForEach-Object {
    Disconnect-LoggedOnUser -ComputerName $_.ComputerName -Id $_.ID -Verbose 
}

如果我从-Append删除Export-Csv,我就不再遇到循环问题了。但是,并非每个对象都导出到CSV(仅导出列表中的最后一个服务器)。如何将每个服务器导出到CSV,并且只让它运行一次指定的会话?

我发布了我的其余代码(包括两个函数到我的github gist here

这是我得到的示例输出:

VERBOSE: Attempting to disconnect session 24 on XXX
VERBOSE: Error disconnecting session displaying message
WARNING: Error on XX, Could not reset session ID 24, Error code 5

VERBOSE: Attempting to disconnect session 24 on XXX
VERBOSE: Error disconnecting session displaying message
WARNING: Error on XX, Could not reset session ID 24, Error code 5

VERBOSE: Attempting to disconnect session 3 on XX
VERBOSE: Error disconnecting session displaying message
WARNING: Error on XX, Could not reset session ID 3, Error code 5

VERBOSE: Attempting to disconnect session 24 on XXX
VERBOSE: Error disconnecting session displaying message
WARNING: Error on XX, Could not reset session ID 24, Error code 5

VERBOSE: Attempting to disconnect session 3 on XX
VERBOSE: Error disconnecting session displaying message
WARNING: Error on XX, Could not reset session ID 3, Error code 5


VERBOSE: Attempting to disconnect session 14 on XX
VERBOSE: Error disconnecting session displaying message
WARNING: Error on XX, Could not reset session ID 14, Error code 5

1 个答案:

答案 0 :(得分:0)

将函数定义移动到代码的开头并更改

foreach ($Server in $Servers) {
    if (-not (Test-Connection $Server -Count 1 -Quiet)) { continue }

    if (-not (Convert-QueryToObjects $Server -ErrorAction SilentlyContinue)) {
        $openservers += $server
        $openservers | Out-File 'H:\demo\session\openservers.txt'
    } else {  
        Convert-QueryToObjects -Name $Server | Where-Object {
            @('Disconnected','Active') -contains $_.SessionState
        } | Export-Csv H:\demo\session\run11.csv -NoTypeInformation -Append 
    }
}

Import-Csv 'H:\demo\session\run11.csv' | Where-Object {
    ($_.SessionState -eq 'Disconnected') -or
    (($_.IdleTime -like "*:*") -and ($_.IdleTime -gt "00:59"))
} | ForEach-Object {
    Disconnect-LoggedOnUser -ComputerName $_.ComputerName -Id $_.ID -Verbose 
}

类似

$culture = [Globalization.CultureInfo]::InvariantCulture
$reftime = [DateTime]::ParseExact('00:59', 'hh:mm', $culture)

$Servers | Where-Object {
    Test-Connection $Server -Count 1 -Quiet
} | ForEach-Object {
    Convert-QueryToObjects $_ -ErrorAction SilentlyContinue
    if (-not $?) { $openservers += $_ }
} | Where-Object {
    $_.SessionState -eq 'Disconnected' -or
    ($_.SessionState -eq 'Active' -and
    [DateTime]::ParseExact($_.IdleTime, 'hh:mm', $culture) -gt $reftime)
} | ForEach-Object {
    Disconnect-LoggedOnUser -ComputerName $_.ComputerName -Id $_.ID -Verbose 
}

$openservers | Out-File 'H:\demo\session\openservers.txt'