如何在 foreach 并行循环中调用函数

How to call a function within a foreach parallel loop

晚上好。

我是第一次尝试使用并行性,但我不明白如何在 foreach 循环中调用函数。

我收到一系列错误:无法将参数绑定到参数 'Path' 因为它为空。

这是我目前所做的:


$FolderPath = "C:\myfolder\"

function AppendLog ($client) {
    $so = New-CimSessionOption -Protocol 'DCOM'
    $s = New-CimSession -ComputerName $client -SessionOption $so
    Add-Content -Path (join-path $folderpath "LOGS.txt") -Value ( (get-date -Format "[yyyy.MM.dd HH:mm:ss]").tostring() + $client + " -PING: OK")
    $arch = Get-CimInstance –query "select * from win32_operatingsystem" -CimSession $s | select -expandproperty osarchitecture
    Add-Content -Path (join-path $folderpath "LOGS.txt") -Value ( (get-date -Format "[yyyy.MM.dd HH:mm:ss]").tostring() + $client + " -ARCH:" + $arch )   
    $lastboot = Get-CimInstance –query "select * from win32_operatingsystem" -CimSession $s | select -expandproperty lastbootuptime
    Add-Content -Path (join-path $folderpath "LOGS.txt") -Value ( (get-date -Format "[yyyy.MM.dd HH:mm:ss]").tostring() + $client + " -BOOT:" + $lastboot )   

}



$funcDef = $function:AppendLog.ToString()

$clients = get-content -path (join-path $folderPath "client.txt")
$clients | ForEach-Object -parallel  {

    if (test-connection $_ -count 2 -Quiet) 
            {                              
                $function:AppendLog = $using:funcDef
                AppendLog ($_)
            }
     }       -throttlelimit 3

Could you explain me how to pass my path?

我的评论不好,你得到的错误很可能来自你的函数。 Join-Path:

引发错误
PS /> Join-Path $null 'Logs.txt'
Join-Path : Cannot bind argument to parameter 'Path' because it is null.
At line:1 char:11
+ Join-Path $null 'Logs.txt'
+           ~~~~~
    + CategoryInfo          : InvalidData: (:) [Join-Path], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.JoinPathCommand

原因是 $FolderPath 不存在于您的并行循环范围内。 $folderpath 应该在您的函数中替换为 $using:folderpath


附带说明一下,在并行执行时向同一个文件添加信息似乎不是一个好主意。


最后一次编辑,我知道这是否是为了测试 ForEach-Object -Parallel 的工作原理,但同样,如果该 cmdlet 允许同时对多个主机进行远程查询/远程执行,请让该 cmdlet 为您处理,效率更高

至于代码,这是我将与您已有的代码一起使用的代码:

$FolderPath = "C:\myfolder\"
$sessionOption = New-CimSessionOption -Protocol 'DCOM'

$clients = Get-Content -Path (Join-Path $FolderPath -ChildPath "Client.txt")
$results = $clients | ForEach-Object -Parallel {

    $out = @{
        Time = [datetime]::Now.ToString('[yyyy.MM.dd HH:mm:ss]')
        ComputerName = $_
    }

    if ($ping = Test-Connection $_ -Count 2 -Quiet)
    {
        $session = New-CimSession -ComputerName $_ -SessionOption $using:sessionOption
        $OSInfo = Get-CimInstance -CimSession $session -ClassName win32_operatingSystem
        Remove-CimSession $session
    }

    $out.Ping = $ping
    $out.Arch = $OSInfo.OSArchitecture
    $out.LastBoot = $OSInfo.LastBootUpTime

    [pscustomobject]$out

} -ThrottleLimit 3

$results | Export-Csv "$myFolder\LOGS.csv" -NoTypeInformation

这将输出如下所示的对象:

Time                  ComputerName   Ping   OSArchitecture LastBoot             
----                  ------------   ----   -------------- --------             
[2021.06.19 20:06:00] ComputerName01 True   64-bit         6/16/2021 11:47:16 AM
[2021.06.19 20:07:00] ComputerName02 False
[2021.06.19 20:08:00] ComputerName03 True   64-bit         6/13/2021 11:47:16 AM
[2021.06.19 20:09:00] ComputerName04 True   64-bit         6/14/2021 11:47:16 AM
[2021.06.19 20:10:00] ComputerName05 True   64-bit         6/15/2021 11:47:16 AM

可以很好地导出为 CSV 而不是文本文件。 P.D.: 对不起语法高亮:(