1

It must be obvious but I do not get it being fairly new in PowerShell, can anybody explain why I can not 'pipe' the outcome of the following commands further:

Get-Process | Where-Object { $_.ProcessName -match 'acc' } |
    Select-Object -Property id, Name

This gives an out put as:

   Id Name
   -- ----
11744 MSACCESS

I would expect I can do the following:

Get-Process | Where-Object { $_.ProcessName -match 'acc' } |
     Select-Object -Property id, Name |
     write-host $_.name

or

Get-Process | Where-Object { $_.ProcessName -match 'acc' } |
    Select-Object -Property id, Name | $_ 

I suppose I miss something here. Thx to all.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Vsn
  • 21
  • 3
  • This is not a piping issue. Depending on object type you get different outputs which is built into PS. Some object types you can just type the variable name and get all the properties, other types you need to add Write-Host to get value. Others you may need to pipe to Format-Table. – jdweng Mar 05 '23 at 10:06
  • What is your desired output? – stackprotector Mar 05 '23 at 11:12
  • In short: The automatic `$_` variable (whose alias is `$PSItem`) is only ever meaningfully defined inside _script blocks_ (`{ ... }`), such as in `ForEach-Object` and `Where-Object` calls. See the linked duplicate for details. – mklement0 Mar 05 '23 at 13:16
  • @jdweng, the only problem with the commands in the question is the use of `$_` outside a script block. Your comment is a distraction that includes bad advice ("you need to add Write-Host to get value"). – mklement0 Mar 05 '23 at 13:22
  • As an aside: [`Write-Host` is typically the wrong tool to use](http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/), unless the intent is to write _to the display only_, bypassing the success output stream and with it the ability to send output to other commands, capture it in a variable, redirect it to a file. To output a value, use it _by itself_; e.g., `$value` instead of `Write-Host $value` (or use `Write-Output $value`, though that is rarely needed). See also: the bottom section of [this answer](https://stackoverflow.com/a/50416448/45375). – mklement0 Mar 05 '23 at 13:24
  • @mklement0 : You are not answering the OPs question. The question is about piping. In this case the object is the results from Get-Process, but in other cases the object is different. Some case the object is a straight array and other case it is a complex object. – jdweng Mar 05 '23 at 13:50
  • @jdweng, yes, the question is about piping, and so is my answer. I read the question to be about _further processing_ of objects in a pipeline, with a mistaken attempt to use `$_` outside a script block. And the fix for that is `... | ForEach-Object { $_.Name }`, for instance. Of course the objects in a given pipeline can be of any type, but how is that relevant? And why would you focus on their for-display formatting? – mklement0 Mar 05 '23 at 14:46

1 Answers1

0

Try this:

Get-Process | Where-Object { $_.ProcessName -match 'acc' } |
    Select-Object -Property id, Name | % {$_}

By doing a foreach-object (coded as %) you enable processing for each object. You could also put in $.name or $.id.

Walter Mitty
  • 18,205
  • 2
  • 28
  • 58
  • thanks, by some reading of the answers, i do understand the $PSitem / $_ better. however, this was a 'demo' I eventually wanted to stop the process so pipe the output to stop-process cmdlet. I still do not see how to do this. I have tried: Get-Process | Where-Object { $_.ProcessName -match 'word' } | Select-Object -Property id, Name | Stop-Process -ProcessName $_.Name – Vsn Mar 05 '23 at 14:43
  • @Vsn, you're still using `$_` _outside a script block_. Aside from that, you can bypass that problem simply with `Get-Process *word* | Stop-Process`. If you did want to stick with your approach and wanted to avoid a `ForEach-Object` call, you can use a _delay-bind script block_: `Get-Process | Where-Object { $_.ProcessName -match 'word' } | Select-Object -Property id, Name | Stop-Process -ProcessName { $_.Name }`. All of this is discussed in the linked duplicate – mklement0 Mar 05 '23 at 14:49
  • 1
    Thanks for all comments, by reading about the $_ / $PSItem i do understand it better now. To answer / complete my query; my idea was to use the output to stop process like this: Get-Process | Where-Object { $_.ProcessName -match 'word' } | Select-Object -Property id, Name | tee-object -file .\stopped.txt | foreach-object { stop-process $_.id } ; get-content .\stopped.txt But the last reply was best and shortest get-process *word* | stop-process, just made it like this to have a terminal output: $s = get-process *word* ; $s ; Stop-Process $s.id This works now for my goal. Thx again. – Vsn Mar 05 '23 at 15:12
  • Is this a case of the XY problem? – Walter Mitty Mar 06 '23 at 15:21