Search code examples
powershellforeachparallel.foreach

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


Please advise, any insight as to what i need to do to have the variable passed successfully would be much appreciated.

This works successfully, but works on each FQDN in the piped list one at a time. i have 100+ servers, so this can take longer than one would think. like 1-6 seconds per server


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

if i add the -Parallel parameter, it fails immediately with the error below. How else am i supposed to give the variable if an automatic variable is the only way I'm seeing that foreach-object pipes them? (I'm hoping that's wrong)

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.

Here's the script with the Parallel parameter inserted to show exactly where i'm doing that


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

Solution

  • Invoke-command computername comp1,comp2,comp3 already runs in parallel.

    # 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