Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate over PSObject properties in PowerShell

Tags:

powershell

I have this PSObject (from XML):

bool : {IsActive, ShowOnB2C, ShowOnB2B, IsWebNews}
str  : {id, ProductId, GroupName, Unit...}
int  : {ProductIdNumeric, Prices_SalesOne, Prices_Treater, Prices_B2C...}
arr  : {EnvironmentBrands, Catalogs, NavisionLevels}
long : long

I would like to iterate over the properties without using the property names, for instance bool.

I have tried to index into the object like this:

$document[0]

But that gives me nothing, but it does not cause any errors either.

Select-Object kind of works, but then I have to use the property names, and I don't want that.

$documents | Select-Object bool,str

ForEach do not iterate the properties.

$documents | ForEach {
    $_.name
}

returns doc and that is the name of the tag (XML) holding the bools, ints, and strings.

like image 782
user1359448 Avatar asked Jun 07 '16 20:06

user1359448


People also ask

How to loop through the properties of a PowerShell object?

How to loop through the Properties of a PowerShell Object. If you have want to iterate through a hashtable to make use of the key/value pairs, you can do that using the GetEnumerator () function and foreach.

What is a psobject in PowerShell?

All objects that are created in a PowerShell session, be they .NET types, COM objects or the explicit «void» object PSCustomObject, are wrapped into a PSObject, which itself is implemented in the .NET type System.Management.Automation.PSObject. These PSObjects might be stored in a variable (to name them) or flow (anonymously) through a pipeline.

How to use pscustomobject in PowerShell foreach parallel loop?

How to use PSCustomObject in PowerShell foreach parallel loop? To use the PSCustomObject inside the Foreach Parallel loop, we first need to consider how we are using the variables inside the loop. So let see if we can store or change a value in the $out variable.

How to keep order of properties in custom PS objects in PowerShell?

PowerShell – Keep Order of Properties in Custom PS Objects January 12, 2021 by Morgan In PowerShell, we use PSObject and Hashtable to keep and control a set of properties and values as custom objects. Sometimes, you may face a problem in displaying properties in the same order as we set in the object.


3 Answers

This is possible using the hidden property PSObject:

$documents.PSObject.Properties | ForEach-Object {
    $_.Name
    $_.Value
}

This won't work with certain PowerShell-created objects (PSObjects) that contain "NoteProperties" (properties of type NoteProperty).

See this answer for a method that covers all property types.

like image 139
briantist Avatar answered Oct 10 '22 22:10

briantist


I prefer using foreach to loop through PowerShell objects:

foreach($object_properties in $obj.PsObject.Properties)
{
    # Access the name of the property
    $object_properties.Name

    # Access the value of the property
    $object_properties.Value
}

Generally, foreach has higher performance than Foreach-Object.

And yes, foreach is actually different than Foreach-Object under the hood.

like image 27
Kellen Stuart Avatar answered Oct 10 '22 23:10

Kellen Stuart


You might need NoteProperty too with Get-Member.

$documents | Get-Member -membertype property,noteproperty | 
  Foreach name

EDIT: type "properties" seems a more generic catchall

$documents | get-member -type properties | % name

EDIT: dump out all the values:

$obj = ls test.ps1
$obj | Get-Member -Type properties | foreach name | 
  foreach { $_ + ' = ' + $obj.$_ }

Attributes = Normal
CreationTime = 06/01/2019 11:29:03
CreationTimeUtc = 06/01/2019 15:29:03
Directory = /Users/js
DirectoryName = /Users/js
Exists = True
Extension = .ps1
FullName = /Users/js/test.ps1
IsReadOnly = False
LastAccessTime = 06/05/2019 23:19:01
LastAccessTimeUtc = 06/06/2019 03:19:01
LastWriteTime = 06/01/2019 11:29:03
LastWriteTimeUtc = 06/01/2019 15:29:03
Length = 55
Name = test.ps1

An alternative way without "| foreach name", that needs extra parentheses:

$obj | Get-Member -Type properties | 
  foreach { $_.name + ' = ' + $obj.($_.name) }

Another take which results in an array that's easier to work with, and might be good for objects converted from json:

$a = '{ prop1:1, prop2:2, prop3:3 }' | convertfrom-json     
$a

prop1 prop2 prop3
----- ----- -----
    1     2     3

$a.PSObject.Properties | select name,value

name  value
----  -----
prop1     1
prop2     2
prop3     3
like image 11
js2010 Avatar answered Oct 10 '22 22:10

js2010