Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell recursive object properties

I need a method that gives me all the properties of an object (recursively). It is not known how many sub-objects the transferred object has.

Example object:

$Car = [PSCustomObject] @{
    Tire          = [PSCustomObject] @{
        Color = "Black"
        Count = 4
    }

    SteeringWheel = [PSCustomObject]@{
        Color   = "Blue"
        Buttons = 15
    }
}

Thank you so much!

like image 492
Alex Avatar asked Oct 19 '25 05:10

Alex


2 Answers

Use the hidden psobject member set to enumerate the properties, then recurse:

function Resolve-Properties 
{
  param([Parameter(ValueFromPipeline)][object]$InputObject)

  process {
    foreach($prop in $InputObject.psobject.Properties){
      [pscustomobject]@{
        Name = $prop.Name
        Value = $prop.Value
      }
      Resolve-Properties $prop.Value
    }
  }
}

Output (with your sample object hierarchy):

PS C:\> Resolve-Properties $Car

Name          Value
----          -----
Tire          @{Color=Black; Count=4}
Color         Black
Length        5
Count         4
SteeringWheel @{Color=Blue; Buttons=15}
Color         Blue
Length        4
Buttons       15

Be careful, the function shown above makes no effort to protect against infinitely looping recursive references, so:

$a = [pscustomobject]@{b = [pscustomobject]@{a = $null}}
$a.b.a = $a
Resolve-Properties $a

Will send your CPU spinning

like image 62
Mathias R. Jessen Avatar answered Oct 22 '25 03:10

Mathias R. Jessen


Based on the answer of @Matthias I modified to get a different type of list output since "I needed it that way".

function Get-PropertiesRecursive {
    param (
        [Parameter(ValueFromPipeline)][object]$InputObject,
        [String]$ParentName
    )
    if ($ParentName) {$ParentName +="."}
    foreach ($Property in $InputObject.psobject.Properties) {
        if ($Property.TypeNameOfValue.Split(".")[-1] -ne "PSCustomObject") {
            [pscustomobject]@{
                TypeName = $Property.TypeNameOfValue.Split(".")[-1]
                Property = "$ParentName$($Property.Name)"
                Value = $Property.Value
            }
        } else {
            Get-PropertiesRecursive $Property.Value -ParentName "$ParentName$($Property.Name)"
        }
    }
}

If you call it with the variable name as -ParentName as option you will get this list:

Get-PropertiesRecursive $Car -ParentName '$Car'

TypeName Property                   Value
-------- --------                   -----
String   $Car.Tire.Color            Black
Int32    $Car.Tire.Count            4    
String   $Car.SteeringWheel.Color   Blue 
Int32    $Car.SteeringWheel.Buttons 15   

And just as Matthias I was too lazy to add property-loop protection, it would have blown up that example.

like image 39
Joachim Otahal Avatar answered Oct 22 '25 05:10

Joachim Otahal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!