foreach - 与 powershell 7 并行

foreach -parallel with powershell 7

我正在努力解决以下问题。我正在尝试从我们的 2016 年终端服务器接收当前安装的边缘版本。 但是当我 运行 时,powershell 下面的代码显示我安装了版本 95.0.1020.30。

$Servers = get-content C:\users\xxx\Documents\Servers.txt 

$servers|foreach-object -parallel {
   Get-Ciminstance -ComputerName $Servers -Class Win32_Product  | where {$_.Name -Like "*Edge*"} | foreach {$_.Version}
   } 

现在到了有趣的部分:当我使用通常的 foreach 循环时,它会返回正确的版本。

$Servers = get-content C:\users\cma-admin\Documents\Servers.txt
 foreach($server in $servers){
Get-Ciminstance -ComputerName $Server -Class Win32_Product  | where {$_.Name -Like "*Edge*"} | 
 foreach {$_.Version}

}

我很乐意将它与“-parallel”一起使用,因为它可以更快地获取这些信息。 我确实在强大的互联网上爬了很多,但我没有发现任何特定于这个“错误”的东西。 我不太确定我是否正确使用了 foreach -parallel。

此致,

黏土

使用$servers | foreach-object -parallel { ... }需要在脚本块内使用automatic $_ variable引用当前服务器(管道输入对象):

$servers|foreach-object -parallel {
   # Note the use of $_
   Get-Ciminstance -ComputerName $_ -Class Win32_Product |
     where {$_.Name -Like "*Edge*"} |
       foreach {$_.Version}
} 

但是,不需要循环(具有并行性),因为 CIM cmdlets,例如 Get-CimInstance, 具有并行性内置,您可以简单地通过传递一个数组[=服务器名称的 37=] 到 -ComputerName:

Get-Ciminstance -ComputerName $servers -Class Win32_Product |
  where Name -Like "*Edge*" |
    foreach Version

注:上面使用了simplified syntax.

结果将不分先后出现。 您可以使用 PowerShell 装饰所有输出对象的 .PSComputerName 属性 来标识特定结果对象的来源服务器。

win32_product class 是出了名的慢,因为它会验证每个 msi。像 get-package 这样的东西会快得多,但是你需要远程 powershell。这也将 运行 并行。除非 Edge 是通过 msi 安装的,否则无论如何它都不会显示 win32_product。

invoke-command $servers { get-package *edge* | ft -a } 

Name                            Version      Source ProviderName
----                            -------      ------ ------------
Microsoft Edge                  96.0.1054.62        Programs
Microsoft Edge Update           1.3.153.55          Programs
Microsoft Edge WebView2 Runtime 96.0.1054.62        Programs

感谢 mklement0 发布正确答案! 我发现当我使用

$servers|foreach-object -parallel {


 Get-Ciminstance -ComputerName $Servers -Class Win32_Product  | where {$_.Name -Like "*Edge*"} | foreach {$_.Version}
   } 

它返回本地安装的 Edge 版本。

多亏了 js2010,我会用 get-package 试试看