4

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.

2
  • If this is for a custom type which you will use a lot, you might want to look into creating a custom ps1xml file for your type (start by reading Get-Help about_types.ps1xml). Otherwise, you could use my answer below. Commented Apr 27, 2014 at 13:00
  • Yes I am ready to create a custom ps1xml file but the issue is that I am unable to find how to do it in ps1xml file also. I want the output to be somethings like this(in list format) : Name:outerName \n InnerThingy:{Name:innerName, Description:innerDescription, myChild:InnerInnerType}. Thus I would like to display the objects with one level of nesting in this manner. Is this possible? Commented Apr 28, 2014 at 1:23

1 Answer 1

3

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.