user3351603
user3351603

Reputation: 51

Can we show the nested objects in Powershell?

I am adding a .NET type to PowerShell session using Add-Type and then creating object of that type using New-Object. This is done as follows:

Add-Type -AssemblyName OuterObj
$a = New-Object OuterObj

Object of type OuterObj is successfully created. Now .NET type $a has a field named innerObj which is object of another .NET type innerObject. So I add innerObject .NET type and create an instance using New-Object:

Add-Type -AssemblyName innerObject
$b = New-Object innerObject

Object of type innerObject is also successfully created. Now I do as follows:

$a.innerObj = $b

Now when I print $a, it shows something like this:

innerObj : innerObject

Thus it does not display the contents of innerObject by default. When I go and explore, innerObj has the fields. I know PowerShell does not show the nested objects by default but instead just shows their types, but is there a way I can specify that what level of nesting of objects PowerShell should show by default? Is there something to specify to show 1 or 2 levels of nested objects?

Any help would be highly appreciated.

Upvotes: 4

Views: 2870

Answers (1)

Robert Westerlund
Robert Westerlund

Reputation: 4838

I don't know of any built-in functionality for this, but it is pretty easy to create a function which should get you where you want to go. Here's an example:

function ConvertTo-NestedPropertyHash
{
    PARAM (
        [Parameter(ValueFromPipeline=$true)]
        [object[]]$InputObject
    ,
        [string[]]$ExpandProperty
    )
    PROCESS 
    {
        foreach($item in $InputObject)
        {
            $hash = @{}
            $processStack = New-Object System.Collections.Stack
            $processStack.Push(@{ Item = $item})
            while($processStack.Count -gt 0)
            {
                $current = $processStack.Pop()
                $prefix = $current.Prefix
                $object = $current.Item
                foreach($property in $object | gm | where membertype -eq "Property")
                {
                    if ($Prefix)
                    {
                        $propertyPath = "$Prefix.$($property.Name)"
                    }
                    else
                    {
                        $propertyPath = $Property.Name
                    }
                    $propertyValue = $object."$($property.Name)"
                    if ($ExpandProperty -contains $propertyPath)
                    {
                        $processStack.Push(@{ 
                            Prefix = $propertyPath
                            Item = $propertyValue
                        })
                    }
                    else
                    {
                        $hash.Add($propertyPath, $propertyValue)
                    }
                }
            }
            Write-Output $hash
        }
    }
}

The above function lets you specify properties (with a dot-notation for subproperties) which you want expanded. So given the following types:

Add-Type -TypeDefinition @"
public class InnerInnerType
{
    public string Name{get;set;}
}
public class InnerType
{
    public string Name{get;set;}
    public string Description{get;set;}
    public InnerInnerType MyChild{get;set;}
}
public class OuterType
{
    public string Name{get;set;}
    public InnerType InnerThingy {get;set;}
}
"@

And the following objects created:

$outer = New-Object OuterType
$inner = New-Object InnerType
$childToInner = New-OBject InnerInnerType
$outer.Name = "outer name"
$inner.Name = "inner name"
$inner.Description = "inner description"
$childToInner.Name = "inner inner thingy"
$outer.innerthingy = $inner
$inner.MyChild = $childToInner

You could use the function without asking it to expand any properties, like so:

$outer | ConvertTo-NestedPropertyHash

Which would yield the following output:

Name                           Value
----                           -----
Name                           outer name
InnerThingy                    InnerType

Or you could ask it to expand the InnerThingy property:

$outer | ConvertTo-NestedPropertyHash -ExpandProperty InnerThingy

Which yields:

Name                           Value
----                           -----
InnerThingy.MyChild            InnerInnerType
Name                           outer name
InnerThingy.Description        inner description
InnerThingy.Name               inner name

Or you could also specify nested properties using dot-notation (current implementation of the function requires that you expand a property to be able to expand sub-properties from that property, so you'd need to do -ExpandProperty InnerThingy, "InnerThingy.MyChild" if you want to expand the MyChild nested property), like the following:

$outer | ConvertTo-NestedPropertyHash -ExpandProperty InnerThingy, "InnerThingy.MyChild"

Which yields:

Name                           Value
----                           -----
Name                           outer name
InnerThingy.Description        inner description
InnerThingy.MyChild.Name       inner inner thingy
InnerThingy.Name               inner name

Upvotes: 3

Related Questions