title: How can I use the -PipelineVariable parameter with a cmdlet that processes its input in parallel?
body: <p>I am querying Active Directory for a list of computers and using <code>Invoke-Command</code> to retrieve data from each one.  Because I am calling <code>Invoke-Command</code> twice for each computer - once with the <code>-FilePath</code> parameter and once with the <code>-ScriptBlock</code> parameter - I am using <code>New-PSSession</code> to create a single session per computer ahead of time.  As the list of computers to process is potentially very long, I am relying on the fact that, when passing multiple values for the <code>-ComputerName</code> parameter to the <code>New-PSSession</code> cmdlet, it initiates the connections in parallel.</p>
  
  <p>The output for each computer is a <code>PSObject</code> containing the results of the calls to <code>Invoke-Command</code> as well as information about the computer; I am using the <code>-PipelineVariable</code> common parameter to persist this information from earlier in the pipeline.  What I am finding, however, is that in my final <code>ForEach-Object</code> block the <code>$_</code> variable (the <code>PSSession</code> object) doesn't always match up with the <code>$computerInfo</code> variable (the pipeline object storing Active Directory computer information); I am getting the same value for <code>$computerInfo</code> multiple iterations in a row with different sessions.  I have inserted some debugging code that illustrates how the value of <code>$computerInfo</code> differs before and after the invocation of <code>New-PSSession</code>:</p>
  
  <pre><code>$sessionOption = New-PSSessionOption -NoMachineProfile;
  
  Get-ADComputer -Filter $computerFilter -Properties 'Description', 'OperatingSystem' `
      | Where-Object -Property 'DistinguishedName' -Match -Value $DistinguishedNamePattern `
          -PipelineVariable 'computerInfo' `
      | Select-Object -First 10 `
      | ForEach-Object {
          Write-Host "Before New-PSSession: $($computerInfo.Name)";
  
          return $_;
      } `
      | Select-Object -ExpandProperty 'Name' `
      | New-PSSession -SessionOption $sessionOption `
      | ForEach-Object {
          Write-Host " After New-PSSession: $($computerInfo.Name)";
  
          $session = $_;    
          try
          {
              New-Object -TypeName 'PSObject' -Property @{
                  DistinguishedName   = $computerInfo.DistinguishedName;
                  Computer            = $computerInfo.Name;
                  OperatingSystem     = $computerInfo.OperatingSystem;
                  Description         = $computerInfo.Description;
                  InvokeScriptResult1 = Invoke-Command -FilePath    $scriptPath  -Session $session;
                  InvokeScriptResult2 = Invoke-Command -ScriptBlock $scriptBlock -Session $session;
              };
          }
          finally
          {
              Remove-PSSession -Session $session;
          }
      };
  </code></pre>
  
  <p>Here is some sample console output:</p>
  
  <pre><code>Before New-PSSession: COMPUTER1
  Before New-PSSession: COMPUTER2
  Before New-PSSession: COMPUTER3
   After New-PSSession: COMPUTER3
   After New-PSSession: COMPUTER3
  Before New-PSSession: COMPUTER4
   After New-PSSession: COMPUTER4
  Before New-PSSession: COMPUTER5
  Before New-PSSession: COMPUTER6
  Before New-PSSession: COMPUTER7
  Before New-PSSession: COMPUTER8
   After New-PSSession: COMPUTER8
   After New-PSSession: COMPUTER8
  Before New-PSSession: COMPUTER9
   After New-PSSession: COMPUTER9
  Before New-PSSession: COMPUTER10
   After New-PSSession: COMPUTER10
   After New-PSSession: COMPUTER10
   After New-PSSession: COMPUTER10
  </code></pre>
  
  <p>Note that in the <code>Before New-PSSession</code> lines all ten computers appear exactly once, whereas in the <code>After New-PSSession</code> lines computers 3, 8, and 10 are duplicated and computers 1, 2, 5, 6, and 7 are missing.  I have also tried passing <code>-ThrottleLimit 1</code> to <code>New-PSSession</code> and get similar results.</p>
  
  <p>I suspect that this is a synchronization issue.  Since <code>New-PSSession</code> is opening sessions with multiple computers at once, whenever it pulls a computer from earlier in the pipeline it overwrites <code>$computerInfo</code> with that computer.  Further down the pipeline where I'm doing my processing it sees the same <code>$computerInfo</code> variable, so while it's processing a session from earlier in the input sequence <code>$computerInfo</code> contains whatever computer <code>New-PSSession</code> just started connecting to.  Is this a bug?  Or is <code>-PipelineVariable</code> just not compatible with a cmdlet like <code>New-PSSession</code>?  Is there a way I can "capture" <code>$_</code> and <code>$computerInfo</code> immediately after <code>New-PSSession</code> so they always stay in sync?  That's how I expected <code>-PipelineVariable</code> to work, but it seems there is one instance of <code>$computerInfo</code> for the entire pipeline, instead of one per object passed through the pipeline.</p>