2
  1. Get-Process|Get-Member $_, why doesn't this work? If $_ represents current object in pipeline, shouldn't the above output be returning members of each process object?
  2. Will a cmdlet pipeline all its output objects at once to the next cmdlet or as and when there is an object available?
  3. As #1 does not work, when exactly can I use $_ variable? The conditions under which this variable gets created will be more helpful rather than just a cmdlet example to demonstrate the use of $_.
2

2 Answers 2

5

$_ is an automatic variable that is available for use within the scriptblock input of certain cmdlets to represent the current item in the pipeline.

Get-Process | Get-Member $_ doesn't work because you send the pipeline object in to Get-Member via the |, but you then don't have any way to access the internals of Get-Member.

You could do this:

Get-Process | ForEach-Object {
    $_ | Get-Member
}

You would then get a Get-Member output for every item in the collection of objects output by Get-Process, although this would be redundant as each would be the same.

Cmdlets do send the objects down the pipeline one at a time. You can see that with this example:

Get-Process | ForEach-Object {
   $_
   Start-Sleep 1
}

You can see with the added delay that the results are arriving in the ForEach-Object one at a time as soon as they are available.

Other places you can use the $_ variable are in Where-Object and Select-Object. For example:

Get-Process | Where-Object { $_.name -like 'win*' }

Here the Where-Object cmdlet is taking each item of the pipeline and we're using $_ to access the name property of that item to see if it's like the string win. If it is, then it gets sent onwards (and so comes out to the console) if it's not, Where-Object discards it.

You can use $_ in a Select-Object when doing calculated properties. For example:

Get-Process | Select-Object name,@{N='WorkingSetGB';E={$_.WorkingSet / 1GB}}

Here we use $_ to get at the WorkingSet property of each item and then convert it to a GB value by using / 1GB.

1

Yes, $_ represents the current object in the pipeline but since Get-Member takes a pipeline input you just have to pipe the result to the cmdlet:

Get-Process | Get-Member

Another example is

Get-Process | Export-Csv MyFile.csv

Here again, $_ is not needed, because Export-Csv takes pipeline input, and receives the output of Get-Process, one process at a time, through the pipeline. There is a loop inside the implementation of Export-csv, but that need not concern you here.

You typically use $_ when you pipe an object to the ForEach-Object cmdlet:

Get-Process | ForEach-Object {
    Write-Host $_.Name
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.