Clay
Clay

Reputation: 23

foreach -parallel with powershell 7

I'm trying to get my head around following problem. I'm trying to receive from our 2016 Terminalservers the currently installed Edge Version. But when I'm running to code below powershell shows me that version 95.0.1020.30 is installed.

$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}
   } 

Now to the fun part: When I'm using the usual foreach loop it gives me the correct version back.

$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}

}

I would love to use it with "-parallel" because it would be way quicker to get those information. I did crawl the mighty internet quite a lot, but I didn't find anything specific to this "error". I'm not quite sure if I'm using the foreach -parallel correctly.

Best regards,

Clay

Upvotes: 2

Views: 2813

Answers (3)

mklement0
mklement0

Reputation: 437428

Using $servers | foreach-object -parallel { ... } requires that you use the automatic $_ variable to refer to the current server (pipeline input object) inside the script block:

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

However, there is no need for a loop (with parallelism), because the CIM cmdlets, such as Get-CimInstance, have parallelism built in, which you can take advantage of simply by passing an array of server names to -ComputerName:

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

Note: The above uses simplified syntax.

The results will arrive in no particular order. You can use the .PSComputerName property that PowerShell decorates all output objects with to identify the server a particular result object originated from.

Upvotes: 5

Clay
Clay

Reputation: 23

Thanks to mklement0 to posting the correct answer! I found out that when I'm using

$servers|foreach-object -parallel {


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

it gives me back the locally installed version of Edge.

And thanks to js2010 I will try it with get-package

Upvotes: 0

js2010
js2010

Reputation: 27423

The win32_product class is notoriously slow, since it verifies every msi. Something like get-package would be much faster, but then you would need remote powershell. This would run in parallel as well. Unless Edge were installed via msi, it wouldn't show up with win32_product anyway.

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

Upvotes: 1

Related Questions