Powershell 7 ForEach-Object Parallel 在传递给 invoke-command 时中断自动变量

Powershell 7 ForEach-Object Parallel breaks automatic variable when passed to invoke-command

请告知,任何关于我需要做什么才能成功传递变量的见解都将不胜感激。

此操作成功,但一次对管道列表中的每个 FQDN 都起作用。我有 100 多台服务器,所以这可能比人们想象的要花更长的时间。每台服务器 1-6 秒


    Write-Host "Confirm correct OS is installed" -ForegroundColor Yellow -BackgroundColor Black

    $FQDNs | ForEach-Object {
        Invoke-Command -ComputerName $_ -Credential $Credentials -ScriptBlock { 
            $OS = (Get-CimInstance -ClassName CIM_OperatingSystem).Caption
            Write-Host "$Using:_`: $OS" -ForegroundColor Green -BackgroundColor Black
            Write-Output "$Using:_`: $OS"
        }
    }
} 

如果我添加 -Parallel 参数,它会立即失败并显示以下错误。如果自动变量是我看到的 foreach-object 管道它们的唯一方式,我还应该如何给变量? (我希望这是错误的)

ForEach-Object: C:\Scripts\Checklist.ps1:53
Line |
  53 |      $FQDNs | ForEach-Object -Parallel {
     |               ~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The value of the using variable '$using:_' cannot be retrieved because
     | it has not been set in the local session.

这是插入了 Parallel 参数的脚本,以准确显示我正在执行的操作


    Write-Host "Confirm correct OS is installed" -ForegroundColor Yellow -BackgroundColor Black

    $FQDNs | ForEach-Object -Parallel {
        Invoke-Command -ComputerName $_ -Credential $Credentials -ScriptBlock { 
            $OS = (Get-CimInstance -ClassName CIM_OperatingSystem).Caption
            Write-Host "$Using:_`: $OS" -ForegroundColor Green -BackgroundColor Black
            Write-Output "$Using:_`: $OS"
        }
    }
}

问题显然是 PowerShell 并不总是正确处理 嵌套上下文 ,在这种情况下,因为添加 -Parallel 参数会创建一个独立的 运行space 每个脚本块实例 运行 并行,$Using: 现在评估那个 运行space 上下文而不是以前执行它的远程会话上下文 没有参数。

如果交替使用 Invoke-Command-ThrottleLimit 以及传入 -ComputerName 的计算机名称数组以利用并行性而不是 ForEach-Object-Parallel.

要解决此问题,请尝试使用 [scriptblock]::Create() 构建您的脚本块,以便遵循正确的上下文,如 中所述。

Invoke-command computername comp1,comp2,comp3 已经并行运行。

# elevated prompt
start-service winrm
invoke-command localhost,localhost,localhost { sleep 10 } 
(get-history)[-1] | fl

Id                 : 3
CommandLine        :     invoke-command localhost,localhost,localhost { sleep 10 }
ExecutionStatus    : Completed
StartExecutionTime : 6/19/2020 10:05:02 AM
EndExecutionTime   : 6/19/2020 10:05:13 AM  # 11 seconds for all three