Search code examples
multithreadingpowershellperformance

Invoke-command very slow


I have a PS script with invoke-command. I want to update the value if I haven't retrieved anything for that machine before.

This command takes long time. We have about 10000 computers inside computers CSV file.

Invoke-Command -ComputerName accepts an array of computers

How can I speed up the this script?

Here is my script :

$computers = Import-Csv "C:\temp\computers.csv"

$AllResults = foreach ($computer in $computers) {
    try {
      if (($computer.Appx -eq 'Port closed or computer unreachable') -Or ($null -eq $computer.Appx)){
       Invoke-Command -ComputerName $computer.name -ScriptBlock { Get-AppxPackage -AllUsers } -ErrorAction 'Stop' | ForEach-Object {
        [pscustomobject]@{
            "ComputerName" = $computer.Name
            "Appx"         = $_.Name -join ";"
          }
        }
      }
    }
    catch {
        [pscustomobject]@{
            "ComputerName" = $computer.Name
            "Appx"         = "Port closed or computer unreachable"
        }
    }
}

$AllResults | Export-Csv -Path "C:\Temp\MSStoreReport.csv" -NoTypeInformation -Encoding 'UTF8'

Solution

  • Use PowerShell 7 and the Foreach-Object -Parallel cmdlet parameter:

    Import-Csv "C:\temp\computers.csv" |Foreach-Object -Parallel {
        $Computer = $_
        try {
          if (($Computer.Appx -eq 'Port closed or computer unreachable') -Or ($null -eq $Computer.Appx)){
           Invoke-Command -ComputerName $Computer.Name -ScriptBlock { Get-AppxPackage -AllUsers } -ErrorAction 'Stop' | ForEach-Object {
            [pscustomobject]@{
                "ComputerName" = $Computer.Name
                "Appx"         = $_.Name -join ";"
              }
            }
          }
        }
        catch {
            [pscustomobject]@{
                "ComputerName" = $Computer.Name
                "Appx"         = "Port closed or computer unreachable"
            }
        }
    } |Export-Csv -Path "C:\Temp\MSStoreReport.csv" -Encoding 'UTF8'
    

    You might want to play with the -ThrottleLimit parameter to define howmany threads/remote computers you want to handle in parallel.