Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between select-object and using foreach on the same object

Tags:

powershell

Can someone please help me understand the difference between the below two pieces of code . Why are the results different for both . I each case i am selecting the same property (name) :

Code 1 :

$obj = Get-Service | Where-Object {$_.Status -eq "Running"} | foreach-object  {$_.Name} | select -first 3
foreach ( $item in $obj ) { write-output "Name is : $item" }
Output :
Name is : AeLookupSvc
Name is : Appinfo
Name is : AudioEndpointBuilder

Code 2 :

$obj = Get-Service | Where-Object {$_.Status -eq "Running"} | select -first 3 name
foreach ( $item in $obj ) { write-output "Name is : $item" }
Output :
Name is : @{Name=AeLookupSvc}
Name is : @{Name=Appinfo}
Name is : @{Name=AudioEndpointBuilder}
like image 756
Subhayan Bhattacharya Avatar asked Oct 11 '14 14:10

Subhayan Bhattacharya


2 Answers

Select-Object returns an array of custom objects to the pipeline; in this case having only one property which happens to be a string.
As @walidtourni mentions, using expand works around this issue. This is because expand causes the output to be the property's value, instead of a custom object with a property with that value. The reason this is possible is expand only takes one argument; i.e. there's no possibility of you attempting to return multiple values for the same "row".

The foreach-object on the other hand is simply spitting stuff out to the pipeline. If you tried to include a second property without manually wrapping both into a custom object, the output would create another row rather than two properties on the same row.

To demonstrate, run the following:

Clear
$x = Get-Service | Where-Object {$_.Status -eq "Running"}  | select -first 3 
$x | foreach-object  {$_.Name}  #returns 3 rows, single column; string
$x | foreach-object  {$_.Name;$_.CanPauseAndContinue;} #returns 6 rows, single column; alternate string & boolean
$x | select Name #returns 3 rows, single column (string); custom object
$x | select Name, CanPauseAndContinue #returns 3 rows, two columns (string & boolean); custom property
$x | select -expand Name #returns 3 rows, single column; string; notice the lack of column header showing this is a string, not a string property of a custom object
$x | select -expand Name,CanPauseAndContinue #error; -expand can only take single valued arguments
$x | select -expand Name -expand CanPauseAndContinue #error; you can't try to define the same paramenter twice
like image 142
JohnLBevan Avatar answered Nov 16 '22 02:11

JohnLBevan


For similar result you can change the second example like this:

select -first 3 -expand name

Select-object select properties object

like image 31
walid toumi Avatar answered Nov 16 '22 03:11

walid toumi