Functions/Productivity/Show-Object.ps1

<#
    .SYNOPSIS
        Show the object as an interactive tree in a separate window.
 
    .DESCRIPTION
        The command will show the specified object in a separate window. The
        object will be shown as an interactive tree, which allows to expand and
        collapse the properties and inspect the object.
 
    .EXAMPLE
        PS C:\> Show-Object -InputObject $object
        Show the object in a separate window.
 
    .EXAMPLE
        PS C:\> Get-Service | Show-Object
        Show the output of the Get-Service command in a separate window.
 
    .NOTES
        Pending features / know issues:
        - Enable the window to be resized
        - Allow pass through of the selected object
        - Add checkboxes for dynamically update the view
        - Ctrl+C does not cancel and close the UI window
 
    .LINK
        https://github.com/claudiospizzi/ProfileFever
#>

function Show-Object
{
    [CmdletBinding()]
    param
    (
        # The object to show.
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
        [AllowNull()]
        [System.Object[]]
        $InputObject,

        # The title of the window.
        [Parameter(Mandatory = $false)]
        [System.String]
        $Title,

        # A flag to enable that the built-in value types like System.Int32
        # (int), System.String (string), System.Boolean (bool), etc. are
        # expanded as normal reference type objects.
        [Parameter(Mandatory = $false)]
        [Switch]
        $ExpandValueType
    )

    begin
    {
        $objects = @()
    }

    process
    {
        $objects += $InputObject
    }

    end
    {
        try
        {
            ##
            ## Prerequisites & Prepare
            ##

            # Load the required assemblies
            Add-Type -AssemblyName 'System.Windows.Forms'

            # Update the title if not specified
            if (-not $PSBoundParameters.ContainsKey('Title'))
            {
                $Title = $MyInvocation.Line
            }

            # Cache variables for performance
            $cacheTypeTreeNodes = @{}

            # Main form specifications
            $mainFormWidth   = 1200
            $mainFormHeight  = 700
            $mainFormPadding = 5

            # One-liner function to convert a png file into a byte array
            # represented as a PowerShell array:
            # PS> ((Get-ChildItem -Filter '*.png' | Out-GridView -OutputMode Single | ForEach-Object { $ms = [System.IO.MemoryStream]::new(); [System.Drawing.Image]::FromFile($_.FullName).Save($ms, 'PNG'); $ms.ToArray() | ForEach-Object { '0x{0:x2}' -f $_ } }) -join ', ') | clip

            # Tree view specifications
            $iconDefinitions = [Ordered] @{
                'Class'     = @{ Id = 0;  Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x01, 0x1b, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0xad, 0x91, 0xb1, 0x4a, 0x03, 0x41, 0x10, 0x86, 0xff, 0x5e, 0x84, 0x88, 0x12, 0x62, 0x2b, 0x88, 0x0f, 0x20, 0x82, 0x90, 0x26, 0xa4, 0xf3, 0x01, 0xf2, 0x26, 0x41, 0x54, 0x72, 0x97, 0x7d, 0x8a, 0xb4, 0x0a, 0x56, 0x5a, 0xe4, 0x19, 0xd2, 0x58, 0x29, 0xc4, 0x48, 0x72, 0x7b, 0x06, 0x24, 0x90, 0x26, 0x08, 0x96, 0xda, 0xd8, 0x98, 0x7f, 0xd6, 0xd9, 0xb0, 0x29, 0x36, 0x77, 0x82, 0x1f, 0xfc, 0xec, 0xed, 0xcc, 0xfc, 0xb3, 0xbb, 0x73, 0xf8, 0x77, 0x26, 0x29, 0x4c, 0x96, 0xe2, 0x6b, 0x62, 0xd0, 0xd4, 0x50, 0x79, 0xd4, 0x3c, 0xe6, 0xda, 0xb2, 0x29, 0xde, 0xad, 0x41, 0x43, 0x53, 0xc5, 0x78, 0xf3, 0xc8, 0xa0, 0xea, 0xf6, 0x5d, 0x5c, 0xb3, 0xc9, 0xbd, 0x4b, 0x16, 0x21, 0x66, 0xca, 0x66, 0x57, 0xd8, 0x0f, 0xf7, 0x7c, 0x46, 0xcd, 0x15, 0x14, 0xc1, 0x93, 0x3f, 0x69, 0x68, 0xc9, 0xb7, 0x98, 0xb9, 0xff, 0xf0, 0x37, 0x09, 0xc9, 0xcf, 0xb1, 0xcd, 0xdc, 0x03, 0x35, 0xb4, 0x97, 0xd8, 0xd5, 0x30, 0x20, 0x6f, 0x95, 0x37, 0x33, 0x71, 0x43, 0x2d, 0xa8, 0xb9, 0x4d, 0x70, 0x1c, 0x6a, 0x9c, 0xe0, 0x44, 0xcd, 0x3d, 0x57, 0xd7, 0xc5, 0x9d, 0xda, 0x7f, 0x91, 0x26, 0x4c, 0xf4, 0xf3, 0x04, 0x75, 0xae, 0xdf, 0xbc, 0xc9, 0x5b, 0x28, 0xc6, 0x7e, 0x9c, 0xd9, 0xe0, 0x54, 0x0e, 0x63, 0xec, 0x4c, 0xad, 0xeb, 0x64, 0x1d, 0x1c, 0xb2, 0x70, 0xaa, 0xdb, 0x15, 0x8c, 0x3d, 0xf2, 0xd4, 0xdb, 0x8d, 0x66, 0x21, 0xd6, 0xe0, 0xe5, 0x02, 0x3b, 0xf2, 0x57, 0x36, 0x9a, 0x85, 0x58, 0x03, 0x61, 0xd4, 0xc6, 0x16, 0x73, 0x03, 0x36, 0x7a, 0x7e, 0x35, 0xd8, 0xd3, 0xf0, 0x3a, 0xda, 0x60, 0x36, 0x35, 0x38, 0x08, 0x95, 0x77, 0x70, 0xc4, 0x78, 0x7c, 0x88, 0x9e, 0xa1, 0x41, 0x85, 0x05, 0x4f, 0x7e, 0x78, 0x5e, 0x8c, 0x95, 0x1b, 0x62, 0x0c, 0x9a, 0xcb, 0x0d, 0x31, 0x46, 0xe9, 0x21, 0xfe, 0x0d, 0x60, 0x09, 0xe9, 0x03, 0xbc, 0x02, 0x93, 0x35, 0xd0, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
                'Interface' = @{ Id = 1;  Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0xc2, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0x63, 0x18, 0x05, 0x44, 0x82, 0xca, 0x33, 0x01, 0x0c, 0xd5, 0x67, 0xce, 0x31, 0x54, 0x9d, 0xf9, 0xc2, 0x50, 0x75, 0xf6, 0x14, 0x90, 0xf6, 0x86, 0xca, 0x40, 0x41, 0xc3, 0x7e, 0x0e, 0x86, 0xca, 0xd3, 0xc9, 0x40, 0x89, 0x14, 0x86, 0xc2, 0x63, 0x9c, 0x50, 0x51, 0x08, 0xa8, 0x3e, 0x1b, 0x08, 0x14, 0xbf, 0xcf, 0x50, 0x75, 0xce, 0x99, 0xa1, 0xe4, 0x22, 0x37, 0x43, 0xcd, 0x69, 0x17, 0x20, 0xff, 0x01, 0xaa, 0x21, 0x55, 0xa7, 0xd7, 0x02, 0x05, 0xfe, 0x43, 0x30, 0x90, 0x8d, 0x0c, 0xaa, 0xcf, 0x9c, 0x01, 0x6b, 0x46, 0x06, 0x55, 0xa7, 0x5d, 0x81, 0x6a, 0x4f, 0x42, 0x79, 0x40, 0x50, 0x75, 0xe6, 0x33, 0xc2, 0x00, 0x2c, 0xb8, 0xe1, 0x2a, 0x0f, 0x54, 0x25, 0x04, 0x94, 0x1d, 0xe1, 0x05, 0x8a, 0x7f, 0x82, 0xf2, 0x80, 0xa0, 0xea, 0xec, 0x1a, 0x84, 0x06, 0x20, 0x1b, 0x19, 0x80, 0x5c, 0x00, 0x72, 0x36, 0x32, 0xc0, 0x70, 0x41, 0xee, 0x6d, 0x76, 0xa0, 0x60, 0x12, 0x38, 0x1c, 0xd0, 0xc3, 0x00, 0x14, 0x80, 0xe0, 0x30, 0x00, 0x6a, 0x02, 0xb9, 0xa4, 0xe2, 0x8c, 0x1b, 0x90, 0xff, 0x10, 0xa8, 0xd6, 0x0b, 0xaa, 0x82, 0x08, 0x50, 0x7d, 0xda, 0x1f, 0x12, 0x16, 0xa0, 0x58, 0x00, 0xda, 0x4c, 0x92, 0xe6, 0x51, 0x40, 0x00, 0x30, 0x30, 0x00, 0x00, 0x21, 0x54, 0x6c, 0xc2, 0xac, 0xca, 0x44, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
                'Method'    = @{ Id = 2;  Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x01, 0x59, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0xb5, 0x92, 0xbd, 0x4a, 0x03, 0x41, 0x14, 0x85, 0x47, 0xb1, 0x53, 0x54, 0x2c, 0x44, 0x44, 0x3b, 0xd1, 0x22, 0x3b, 0xa3, 0x92, 0xce, 0x42, 0x7c, 0x01, 0x1f, 0x41, 0xd1, 0x64, 0x67, 0x0d, 0x82, 0xb5, 0xed, 0x36, 0x4a, 0x20, 0x64, 0x33, 0x1b, 0x11, 0x1b, 0xb1, 0xb0, 0xb1, 0x96, 0x74, 0x96, 0x36, 0x82, 0x82, 0x85, 0x2f, 0x20, 0xa2, 0x45, 0x14, 0x9f, 0xc1, 0x78, 0xce, 0x7a, 0xdd, 0x25, 0xe4, 0x47, 0x0b, 0xfd, 0xe0, 0xb2, 0xf7, 0x9e, 0x73, 0x72, 0xb3, 0xcb, 0x8c, 0xfa, 0x17, 0x42, 0x15, 0x0e, 0x5a, 0x2f, 0x2e, 0x59, 0xed, 0x5e, 0x93, 0x42, 0x4f, 0x4d, 0xec, 0xfe, 0xf8, 0x3a, 0xce, 0xe3, 0x47, 0x37, 0x56, 0xc7, 0xd7, 0x81, 0x8e, 0x74, 0xc1, 0xb8, 0x05, 0xcc, 0x57, 0x81, 0x76, 0xf7, 0x58, 0xb4, 0x22, 0xb1, 0x4e, 0x8a, 0xb9, 0x68, 0xc2, 0x37, 0x2e, 0x46, 0xf8, 0x05, 0xcf, 0x4d, 0xa5, 0x5a, 0x03, 0x62, 0x25, 0x14, 0x4d, 0xb4, 0x0e, 0xef, 0xc9, 0x9a, 0xda, 0x79, 0xc9, 0x54, 0x26, 0x45, 0xce, 0x80, 0x79, 0x8b, 0xba, 0xdc, 0x9b, 0xab, 0x8f, 0x8a, 0xd4, 0x01, 0x3d, 0x66, 0x98, 0x15, 0x29, 0x03, 0x62, 0x0b, 0xd5, 0xc4, 0xab, 0x9e, 0xf9, 0xa6, 0x3e, 0x23, 0x72, 0x0a, 0x35, 0x7a, 0xcc, 0x30, 0x2b, 0x72, 0x06, 0xc5, 0x0d, 0x53, 0x19, 0xc6, 0x73, 0xdf, 0xd7, 0xee, 0x9d, 0x9f, 0xb3, 0xb5, 0x54, 0x1b, 0xdf, 0xcd, 0x1d, 0x8f, 0x04, 0xa6, 0x16, 0x52, 0x83, 0x57, 0x0e, 0xf2, 0xe5, 0xb1, 0x9e, 0x0b, 0xa4, 0x55, 0x85, 0xe5, 0xa3, 0x69, 0x6b, 0xdc, 0x29, 0x34, 0xfe, 0x5b, 0x93, 0x3d, 0x35, 0xb1, 0xdb, 0xb2, 0x29, 0xdd, 0xc4, 0xc0, 0x73, 0x07, 0x2c, 0x19, 0x53, 0x7e, 0xbf, 0x00, 0xaf, 0xce, 0x92, 0x31, 0xa5, 0xd7, 0x82, 0x8f, 0x70, 0x2d, 0x1c, 0x92, 0x31, 0xa1, 0xdb, 0x02, 0x66, 0x98, 0x95, 0x31, 0x03, 0xdf, 0x79, 0x82, 0xcb, 0xf3, 0xb0, 0xa3, 0xdd, 0xaa, 0x48, 0x1d, 0x0b, 0xe8, 0x31, 0xc3, 0xac, 0x48, 0xed, 0xc8, 0x65, 0x79, 0x44, 0xa0, 0xb1, 0xed, 0x55, 0x67, 0xbf, 0x17, 0xe0, 0x24, 0xa6, 0x78, 0x81, 0xe0, 0x3d, 0x7f, 0x5d, 0xb2, 0x3e, 0x24, 0x47, 0x69, 0xe2, 0x43, 0x84, 0xdf, 0x70, 0x74, 0x77, 0x2c, 0xf6, 0xd4, 0xe8, 0x49, 0xec, 0x67, 0xec, 0x62, 0x75, 0xde, 0x7a, 0xee, 0x22, 0x29, 0xf4, 0x22, 0xff, 0x35, 0x4a, 0x7d, 0x02, 0xc1, 0x26, 0xa8, 0x95, 0x87, 0x89, 0x04, 0x36, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
                'Property'  = @{ Id = 3;  Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x01, 0x3c, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0xbd, 0x92, 0x3f, 0x4b, 0x42, 0x61, 0x14, 0xc6, 0x6f, 0xd0, 0x18, 0x34, 0x8b, 0x0e, 0x15, 0x48, 0xe6, 0x20, 0x34, 0x04, 0x0d, 0xde, 0xb8, 0xff, 0xa9, 0xa1, 0x45, 0xd1, 0xa6, 0x96, 0x22, 0x9b, 0x0a, 0xa2, 0x21, 0xc4, 0xa5, 0xcd, 0xa9, 0xbe, 0x80, 0xf8, 0x61, 0x1c, 0x04, 0x09, 0x1c, 0x5c, 0x24, 0xba, 0x91, 0x46, 0x0e, 0x8d, 0x7e, 0x84, 0x7e, 0xef, 0xeb, 0x11, 0xf4, 0xc6, 0x4d, 0x17, 0x7b, 0xe0, 0xe1, 0x7d, 0xce, 0x39, 0xcf, 0x73, 0xde, 0xf7, 0xc2, 0x35, 0x56, 0x0e, 0xdb, 0xb6, 0x0b, 0x8e, 0xe3, 0x74, 0xe0, 0x18, 0x7e, 0x52, 0x3f, 0xd1, 0x5e, 0x9b, 0x4c, 0x17, 0x80, 0x40, 0x0d, 0xb6, 0x5d, 0xd7, 0x3d, 0x80, 0x39, 0xf4, 0xd0, 0xf3, 0xbc, 0xbc, 0x8c, 0xff, 0x06, 0xc6, 0x3d, 0x02, 0xaf, 0x96, 0x65, 0x6d, 0x88, 0x1e, 0xb2, 0xc4, 0x96, 0x59, 0x9e, 0xfa, 0x59, 0x1b, 0xe3, 0xc0, 0x53, 0xef, 0x60, 0x95, 0x05, 0xeb, 0x98, 0xdf, 0xd0, 0xb7, 0xaa, 0x4f, 0xd8, 0x52, 0xcb, 0xe0, 0x48, 0x1b, 0xe3, 0x80, 0xa1, 0x4e, 0xe8, 0x42, 0xf4, 0x91, 0x84, 0x6e, 0xe0, 0x80, 0x25, 0xfb, 0x9c, 0x63, 0x6d, 0x8c, 0x03, 0xe1, 0x0a, 0xa6, 0x86, 0x94, 0xd3, 0x25, 0x21, 0x9f, 0x91, 0xe5, 0x55, 0x87, 0xe8, 0x17, 0x19, 0xfd, 0x06, 0x86, 0x0c, 0x86, 0x01, 0xe6, 0x63, 0x69, 0x69, 0xa8, 0xcf, 0xe1, 0xf6, 0x4d, 0x66, 0x5d, 0x2e, 0x28, 0x4b, 0x7b, 0x1e, 0x0c, 0x76, 0x67, 0xc3, 0xd4, 0x45, 0x74, 0x13, 0x5e, 0xd3, 0x7f, 0x54, 0x33, 0xf8, 0xa0, 0xcd, 0x51, 0xa8, 0x30, 0xfc, 0xc0, 0x70, 0xa2, 0x6a, 0xce, 0x12, 0x0c, 0xe1, 0x15, 0xac, 0xb3, 0xe4, 0x9e, 0x17, 0xec, 0x68, 0x73, 0x14, 0xbe, 0xef, 0xa7, 0x25, 0x7c, 0xaa, 0x6a, 0x74, 0x19, 0xfd, 0x1e, 0x1b, 0x98, 0x45, 0x34, 0xcc, 0x4d, 0x67, 0xe8, 0x30, 0x08, 0x82, 0x6d, 0x6d, 0x58, 0x04, 0xcc, 0xbd, 0x69, 0x98, 0xf3, 0x1c, 0xaa, 0x1f, 0x28, 0xa5, 0x87, 0xcb, 0x80, 0xc0, 0x37, 0x81, 0x2d, 0x6e, 0xbe, 0x44, 0xf7, 0x61, 0x52, 0x46, 0xcb, 0x81, 0xe7, 0x17, 0x09, 0x7d, 0xc1, 0x96, 0x69, 0x9a, 0x09, 0x69, 0xff, 0x07, 0x0c, 0xe3, 0x07, 0x07, 0xd2, 0x74, 0x69, 0x60, 0xf3, 0x38, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
                'Event'     = @{ Id = 4;  Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x01, 0x30, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0xb5, 0x92, 0x3d, 0x2f, 0x04, 0x51, 0x14, 0x86, 0x5f, 0x09, 0xad, 0x42, 0xa1, 0xd0, 0x20, 0x22, 0x82, 0x44, 0xa5, 0x11, 0x85, 0xd6, 0x7f, 0x20, 0x11, 0x21, 0x12, 0x54, 0x2a, 0xc5, 0xce, 0xcc, 0x5e, 0x2a, 0x8d, 0x4e, 0x22, 0xd1, 0x69, 0x35, 0x1a, 0x85, 0x4e, 0x23, 0x2a, 0xcd, 0x46, 0xe6, 0x63, 0x89, 0x04, 0x89, 0x6d, 0x50, 0x2b, 0xc7, 0x73, 0x27, 0x67, 0x25, 0x12, 0xb3, 0xb3, 0xcd, 0x3e, 0xc9, 0x9b, 0x3b, 0xef, 0xf9, 0x98, 0x73, 0xe7, 0xde, 0x51, 0x4f, 0x49, 0x22, 0x6d, 0xa3, 0x6f, 0x94, 0x9b, 0x9a, 0x37, 0x4e, 0xfd, 0x96, 0xee, 0x4c, 0xc3, 0x69, 0x98, 0x86, 0xaf, 0xcc, 0x69, 0xc4, 0xfb, 0x5c, 0xea, 0x8b, 0x23, 0x5d, 0xc7, 0x4e, 0xcb, 0x45, 0x41, 0x15, 0x34, 0x1f, 0xa1, 0x13, 0xb3, 0xde, 0x6f, 0xa0, 0xc6, 0xfd, 0x96, 0x06, 0x2c, 0x54, 0x0e, 0x53, 0x86, 0xfc, 0xf4, 0xa4, 0xa6, 0x51, 0xef, 0xfd, 0x2e, 0xf0, 0x9f, 0x69, 0xa8, 0x85, 0xa2, 0xa0, 0x0a, 0x8a, 0x0f, 0xd1, 0x99, 0x59, 0x25, 0xa1, 0x2e, 0xe3, 0xba, 0x8e, 0xcd, 0x76, 0xe6, 0xc9, 0x69, 0x90, 0xe6, 0x8f, 0x24, 0xd0, 0xa4, 0xf7, 0x71, 0xa8, 0x55, 0x7c, 0xfb, 0x10, 0xf3, 0x2c, 0xd4, 0x62, 0x51, 0x58, 0x06, 0x45, 0xb5, 0xa4, 0xae, 0x73, 0xb3, 0x7f, 0x20, 0xb7, 0x4f, 0xee, 0xd4, 0xec, 0xff, 0x50, 0xd4, 0xcc, 0x02, 0x4d, 0x99, 0xfd, 0x85, 0xf8, 0x1e, 0x7a, 0x6c, 0xdf, 0x4a, 0x29, 0x7c, 0xef, 0x0e, 0x85, 0xc5, 0x76, 0xf9, 0xee, 0x03, 0x8b, 0x6d, 0xe2, 0x5f, 0x52, 0xa7, 0xb1, 0xa2, 0xa8, 0x8a, 0x87, 0x40, 0xd3, 0x34, 0xb4, 0xfc, 0x79, 0x70, 0xf7, 0xeb, 0x3c, 0xbf, 0xb2, 0xab, 0x71, 0x4b, 0x57, 0x43, 0xc3, 0x15, 0xda, 0x4d, 0x23, 0xad, 0xb1, 0xbe, 0xf1, 0xc2, 0x09, 0x4b, 0x55, 0xc3, 0x5d, 0x2f, 0x31, 0xf5, 0x19, 0xad, 0xd0, 0xfc, 0xce, 0x3f, 0x31, 0x63, 0xa9, 0xee, 0xa0, 0xe9, 0x8e, 0xc9, 0x17, 0xac, 0x2d, 0xae, 0x70, 0xd6, 0xc2, 0xdd, 0xc3, 0x29, 0xcf, 0x33, 0xfd, 0x96, 0x75, 0xce, 0x42, 0xbd, 0x44, 0xfa, 0x01, 0x82, 0x38, 0x87, 0xed, 0xca, 0xc3, 0x13, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
                'Object'    = @{ Id = 5;  Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc2, 0x00, 0x00, 0x0e, 0xc2, 0x01, 0x15, 0x28, 0x4a, 0x80, 0x00, 0x00, 0x00, 0x4d, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0x63, 0x18, 0x1c, 0x40, 0xae, 0x5e, 0xee, 0x81, 0x7c, 0x83, 0xfc, 0x7f, 0x5c, 0x18, 0x24, 0x0f, 0x55, 0x8a, 0x1d, 0x80, 0x15, 0xb5, 0xc8, 0x49, 0xe2, 0xc2, 0x20, 0x79, 0xa8, 0x52, 0xec, 0x80, 0x14, 0x03, 0x14, 0x15, 0x15, 0xf7, 0xc3, 0x30, 0x54, 0x88, 0x0a, 0x5e, 0x18, 0xa6, 0x00, 0x39, 0xb0, 0xb0, 0x61, 0xa8, 0xb2, 0x61, 0x03, 0xb0, 0xf9, 0x11, 0x19, 0x43, 0x95, 0xc1, 0xd5, 0x41, 0xb9, 0x83, 0x02, 0x30, 0x30, 0x00, 0x00, 0xac, 0x9c, 0x49, 0x5f, 0x10, 0x19, 0x35, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
                'Null'      = @{ Id = 6;  Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc2, 0x00, 0x00, 0x0e, 0xc2, 0x01, 0x15, 0x28, 0x4a, 0x80, 0x00, 0x00, 0x00, 0x84, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0x63, 0x18, 0x59, 0x40, 0x1f, 0x88, 0x85, 0x21, 0x4c, 0xc2, 0x00, 0xa4, 0x78, 0x05, 0x10, 0xff, 0x87, 0xe2, 0x69, 0x50, 0x3e, 0x51, 0x00, 0x64, 0xcb, 0x3b, 0x20, 0x4e, 0x07, 0xf3, 0x20, 0xfc, 0x3b, 0x40, 0xbc, 0x03, 0xcc, 0x23, 0x02, 0x80, 0x34, 0x82, 0x6c, 0x84, 0x81, 0x08, 0x20, 0x06, 0x89, 0x9d, 0x06, 0x62, 0x90, 0xcb, 0x08, 0x82, 0x32, 0x28, 0x06, 0x01, 0x90, 0x06, 0x98, 0x61, 0xad, 0x40, 0x0c, 0x13, 0xc7, 0x0b, 0x60, 0x06, 0x80, 0x9c, 0x0e, 0xf2, 0x37, 0x2c, 0xe0, 0x88, 0x36, 0x00, 0xe6, 0x05, 0x10, 0x46, 0x76, 0x32, 0xc8, 0x0b, 0x36, 0x10, 0x26, 0x7e, 0x00, 0x0b, 0x44, 0x58, 0xa8, 0x83, 0xf8, 0x20, 0xc3, 0x40, 0x06, 0x10, 0x05, 0x60, 0x4e, 0x47, 0x8f, 0x46, 0x98, 0x57, 0x08, 0x02, 0x90, 0xb3, 0x89, 0x0a, 0xed, 0x61, 0x01, 0x18, 0x18, 0x00, 0x20, 0x96, 0x19, 0xca, 0xa6, 0xe7, 0xeb, 0xae, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
                'String'    = @{ Id = 7;  Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc2, 0x00, 0x00, 0x0e, 0xc2, 0x01, 0x15, 0x28, 0x4a, 0x80, 0x00, 0x00, 0x00, 0x79, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0xed, 0x90, 0xd1, 0x0d, 0x40, 0x40, 0x10, 0x44, 0xb7, 0x07, 0x85, 0x68, 0x40, 0x21, 0x3a, 0xd0, 0x81, 0x52, 0xd4, 0xa2, 0x07, 0x2d, 0xa8, 0x41, 0x0b, 0xcc, 0x4b, 0x76, 0x7e, 0xb8, 0x20, 0x3e, 0xfc, 0x30, 0xc9, 0x8b, 0xbd, 0xb5, 0x3b, 0x99, 0xbb, 0xf8, 0x75, 0xaa, 0x3e, 0x79, 0xac, 0x77, 0x0d, 0x6a, 0x31, 0x26, 0x5e, 0xe2, 0x3b, 0x89, 0x45, 0xcc, 0x82, 0x99, 0x4a, 0x30, 0xb3, 0x66, 0xaf, 0x28, 0x96, 0x18, 0xc6, 0x60, 0xa0, 0x21, 0x75, 0x82, 0x1a, 0x8a, 0xa9, 0x9c, 0x00, 0x67, 0x68, 0x04, 0x83, 0x1e, 0xe6, 0xec, 0x84, 0xd4, 0x07, 0xf1, 0xa3, 0x15, 0x44, 0x24, 0xc1, 0xde, 0xe0, 0x32, 0x01, 0xcb, 0xbe, 0x17, 0xd8, 0x80, 0x9a, 0x3e, 0xa6, 0x98, 0xdf, 0x7a, 0x83, 0x6f, 0x29, 0x62, 0x03, 0xa5, 0x87, 0x22, 0xfd, 0x2e, 0xc3, 0xbb, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
                'Number'    = @{ Id = 8;  Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc2, 0x00, 0x00, 0x0e, 0xc2, 0x01, 0x15, 0x28, 0x4a, 0x80, 0x00, 0x00, 0x00, 0x92, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0xed, 0x91, 0x5b, 0x0d, 0x80, 0x30, 0x0c, 0x45, 0xe7, 0x01, 0x07, 0x18, 0xc0, 0x00, 0x0a, 0x50, 0x80, 0x03, 0x1c, 0xe0, 0x00, 0x0b, 0x68, 0x40, 0x02, 0x1e, 0xb0, 0x80, 0x06, 0x2c, 0xc0, 0x3d, 0x1b, 0x63, 0x8f, 0x2c, 0x7c, 0xf1, 0xc9, 0x49, 0x6e, 0xd6, 0x36, 0xdd, 0x5d, 0x29, 0xe6, 0xe7, 0x3b, 0x2a, 0x69, 0x73, 0xa1, 0xa5, 0x97, 0x0e, 0xe9, 0x94, 0x26, 0x0a, 0xa2, 0x91, 0x76, 0x89, 0x1a, 0x27, 0xf9, 0x03, 0x45, 0x94, 0x83, 0x31, 0xcd, 0xad, 0xcd, 0x02, 0xb3, 0x34, 0xba, 0x30, 0xb0, 0xde, 0x67, 0x0e, 0x93, 0x25, 0xaf, 0x89, 0x45, 0xea, 0x5c, 0x18, 0x28, 0x19, 0xd0, 0x44, 0x73, 0x0c, 0x93, 0xd2, 0xcb, 0x74, 0x09, 0xb9, 0x01, 0xaf, 0x16, 0x1b, 0xc5, 0x20, 0xf1, 0x19, 0x09, 0xb1, 0xc1, 0xdb, 0x65, 0x60, 0xb1, 0x89, 0x81, 0x5f, 0x22, 0x62, 0x61, 0x2c, 0x28, 0xae, 0x91, 0x63, 0xea, 0xff, 0x0c, 0xe6, 0xb5, 0xf4, 0x63, 0x8c, 0xb9, 0x00, 0x04, 0x00, 0x20, 0x9f, 0x98, 0x92, 0xbd, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
                'Boolean'   = @{ Id = 9;  Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc2, 0x00, 0x00, 0x0e, 0xc2, 0x01, 0x15, 0x28, 0x4a, 0x80, 0x00, 0x00, 0x00, 0x7c, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0x63, 0x18, 0x05, 0x44, 0x81, 0x15, 0x40, 0x2c, 0x0c, 0x61, 0xe2, 0x07, 0x20, 0x45, 0xa7, 0x21, 0x4c, 0x14, 0xb0, 0x03, 0x4a, 0xeb, 0x03, 0xf1, 0x1d, 0x20, 0xfe, 0x0f, 0xc4, 0x65, 0x20, 0x01, 0x74, 0x00, 0x92, 0x00, 0x61, 0x64, 0xe0, 0x05, 0xc4, 0xe9, 0x10, 0x26, 0xc3, 0x34, 0x20, 0x06, 0xb1, 0x41, 0x16, 0xbd, 0x83, 0xd2, 0x18, 0x00, 0x66, 0x1b, 0x0c, 0xb4, 0x02, 0x31, 0xc8, 0x66, 0x10, 0x00, 0xc9, 0xd9, 0x40, 0x98, 0x28, 0x6c, 0x14, 0x80, 0x6e, 0x00, 0x32, 0x9f, 0x64, 0x03, 0x94, 0x80, 0x18, 0xe4, 0x6c, 0x18, 0x20, 0xd9, 0x00, 0x90, 0x7f, 0x41, 0x61, 0x00, 0x03, 0x04, 0xc3, 0x00, 0x16, 0x88, 0x20, 0x0c, 0x32, 0x1d, 0x3d, 0xfa, 0x08, 0xc6, 0x02, 0x3a, 0x40, 0x76, 0xcd, 0xf0, 0x05, 0x0c, 0x0c, 0x00, 0xf9, 0x87, 0x1e, 0x3c, 0x50, 0xee, 0x27, 0x71, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
                'Date'      = @{ ID = 10; Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc2, 0x00, 0x00, 0x0e, 0xc2, 0x01, 0x15, 0x28, 0x4a, 0x80, 0x00, 0x00, 0x00, 0xab, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0xcd, 0x91, 0xc1, 0x0d, 0xc4, 0x20, 0x0c, 0x04, 0xa9, 0x92, 0x07, 0x74, 0x00, 0x75, 0xd1, 0x04, 0xd0, 0x06, 0x20, 0x6a, 0xe1, 0xe1, 0xd3, 0x12, 0xa3, 0x4b, 0x44, 0x48, 0xb8, 0xdf, 0x8d, 0x64, 0xd9, 0x86, 0xf5, 0x3a, 0x22, 0xe2, 0x3f, 0x91, 0x52, 0x12, 0x97, 0x97, 0xfa, 0x11, 0x08, 0x77, 0x82, 0xe5, 0x33, 0xb8, 0x1c, 0x38, 0xe7, 0xb8, 0xba, 0xd6, 0xdb, 0x06, 0x2b, 0x5e, 0x0d, 0x76, 0x82, 0xe5, 0x33, 0xb8, 0x7c, 0x83, 0xa5, 0xf7, 0x3c, 0x19, 0x84, 0x10, 0xc8, 0x5a, 0x4b, 0x5a, 0xeb, 0x9e, 0xd1, 0xf3, 0xd8, 0x97, 0x95, 0x41, 0x8c, 0x91, 0x8c, 0x31, 0x94, 0x52, 0xea, 0x83, 0xc8, 0xe8, 0x27, 0x93, 0x95, 0x01, 0x36, 0xe6, 0x9c, 0x7b, 0x3d, 0x34, 0xa5, 0x94, 0x7e, 0xce, 0xa3, 0x07, 0x2b, 0x03, 0xa5, 0x14, 0xb5, 0xd6, 0x7a, 0x0d, 0x0d, 0x02, 0x3d, 0xce, 0x79, 0xf4, 0x60, 0x5c, 0x9e, 0x03, 0xe7, 0xd8, 0x84, 0x8d, 0x67, 0x6e, 0xbf, 0x60, 0xc5, 0x78, 0xc0, 0x5a, 0x6b, 0x1f, 0x46, 0x46, 0xef, 0xbd, 0xdf, 0x33, 0x00, 0x10, 0xe3, 0xe1, 0xf0, 0x17, 0x90, 0x7f, 0x1a, 0x7e, 0x46, 0x88, 0x0f, 0x7a, 0xd7, 0x7f, 0x20, 0xd6, 0x2d, 0x97, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }
                'Enum'      = @{ Id = 11; Data = 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc2, 0x00, 0x00, 0x0e, 0xc2, 0x01, 0x15, 0x28, 0x4a, 0x80, 0x00, 0x00, 0x00, 0x9d, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4f, 0xcd, 0x91, 0x51, 0x0d, 0x80, 0x30, 0x0c, 0x44, 0xe7, 0x01, 0x07, 0x18, 0xc0, 0x00, 0x0a, 0x50, 0x80, 0x03, 0x1c, 0xe0, 0x00, 0x0b, 0x68, 0xc1, 0x03, 0x16, 0xd0, 0x80, 0x05, 0xb8, 0xc7, 0x28, 0xe9, 0x08, 0x09, 0xf0, 0x05, 0x2f, 0xb9, 0xec, 0xb6, 0x65, 0xb7, 0xae, 0x0b, 0xbf, 0x22, 0x93, 0x06, 0x69, 0xd9, 0x47, 0xe6, 0x06, 0x73, 0xbf, 0x77, 0x49, 0x2f, 0x55, 0xd1, 0x86, 0x56, 0xaa, 0xa3, 0xdd, 0xe0, 0x10, 0x6b, 0x30, 0x4a, 0x45, 0xb4, 0x29, 0x76, 0x83, 0xc9, 0x0e, 0x00, 0x7b, 0x65, 0xb4, 0x89, 0x4f, 0xf0, 0x15, 0x9c, 0x79, 0x14, 0xe0, 0x7b, 0x30, 0x4b, 0x3e, 0xec, 0x51, 0xc0, 0xb7, 0xd0, 0x30, 0x6b, 0x9a, 0xf7, 0x80, 0xa7, 0xf3, 0x3c, 0x8b, 0xf2, 0x3b, 0x89, 0x67, 0x32, 0x1e, 0xdc, 0x05, 0xd0, 0x60, 0x20, 0x88, 0xef, 0xa5, 0x5f, 0x13, 0x0b, 0xc6, 0x5d, 0x80, 0xcd, 0xcf, 0xcd, 0x3c, 0x68, 0x24, 0x2b, 0x89, 0xdb, 0x5e, 0x07, 0xe4, 0x12, 0x25, 0xf1, 0x4e, 0xca, 0x7c, 0x1d, 0xf0, 0x15, 0x21, 0xac, 0x7f, 0x9a, 0x31, 0xdb, 0x85, 0x50, 0x9c, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82; }
            }


            ##
            ## Helper Functions
            ##

            <#
                .SYNOPSIS
                    Convert an object to a tree node and add it to the parent.
            #>

            function Add-TreeNodeObject
            {
                [CmdletBinding()]
                param
                (
                    # The parent tree node.
                    [Parameter(Mandatory = $false)]
                    $Parent,

                    # The object to add as tree node.
                    [Parameter(Mandatory = $true)]
                    [AllowNull()]
                    [System.Object]
                    $Object
                )

                # Resolve the object type to a simple type used to decide how to
                # show the object in the output.
                $simpleType = Resolve-SimpleType -Object $Object

                if ($null -eq $Object)
                {
                    $treeNode = [System.Windows.Forms.TreeNode]::new('$null')
                }
                else
                {
                    $treeNode = [System.Windows.Forms.TreeNode]::new(('[{0}] {1}' -f $Object.GetType().FullName, $Object.ToString()))
                }

                if ($simpleType -eq 'Object' -or $ExpandValueType.IsPresent)
                {
                    Add-TreeNodeType -Parent $treeNode -Type $Object.GetType()

                    # Use the Get-Member to get the methods instead of using the
                    # $object.PSObject.Methods property. The Methods property
                    # will return getter, setter, adder, remover methods for
                    # properties and events. They are displayed separately.
                    foreach ($method in @(Get-Member -InputObject $Object -MemberType 'Methods'))
                    {
                        Add-TreeNodeMethod -Parent $treeNode -Method $Object.PSObject.Methods.Where({ $_.Name -eq $method.Name })[0]
                    }

                    # Get all properties and show them as tree nodes.
                    foreach ($property in $Object.PSObject.Properties)
                    {
                        Add-TreeNodeProperty -Parent $treeNode -Property $property
                    }

                    # Get all events and show them as tree nodes.
                    foreach ($event in @(Get-Member -InputObject $Object -MemberType 'Event'))
                    {
                        Add-TreeNodeEvent -Parent $treeNode -Event $event
                    }
                }

                $treeNode.Tag = $Object

                $treeNode.ImageIndex         = $iconDefinitions.$simpleType.Id
                $treeNode.SelectedImageIndex = $iconDefinitions.$simpleType.Id

                $Parent.Nodes.Add($treeNode) | Out-Null
            }

            <#
                .SYNOPSIS
                    Convert a type to a tree node and add it to the parent.
            #>

            function Add-TreeNodeType
            {
                [CmdletBinding()]
                param
                (
                    # The parent tree node.
                    [Parameter(Mandatory = $false)]
                    # [System.Windows.Forms.TreeNode]
                    $Parent,

                    # The type definition to show.
                    [Parameter(Mandatory = $true, ParameterSetName = 'Type')]
                    [System.Type]
                    $Type,

                    # The type name definition to show.
                    [Parameter(Mandatory = $true, ParameterSetName = 'Name')]
                    [System.String]
                    $Name
                )

                # If the type was specified by name, try to resolve the name and
                # add it as type and update the type's full name. If the type
                # was specified directly, use it and populate the name.
                if ($PSCmdlet.ParameterSetName -eq 'Name')
                {
                    $Type = Resolve-Type -TypeName $Name
                    if ($null -ne $Type)
                    {
                        $Name = $Type.FullName
                    }
                }
                else
                {
                    $Name = $Type.FullName
                }

                if ($cacheTypeTreeNodes.ContainsKey($Name))
                {
                    $treeNode = $cacheTypeTreeNodes[$Name].Clone()
                }
                else
                {
                    if ($null -ne $Type)
                    {
                        # Create a full type node with base type and interfaces
                        $treeNode = [System.Windows.Forms.TreeNode]::new($Name)

                        # Add the base type as the first child node
                        if ($null -ne $Type.BaseType)
                        {
                            Add-TreeNodeType -Parent $treeNode -Type $Type.BaseType
                        }

                        # Add the implemented interfaces as child nodes
                        foreach ($typeImplementedInterface in $type.ImplementedInterfaces)
                        {
                            $treeNodeInterface = [System.Windows.Forms.TreeNode]::new($typeImplementedInterface.FullName)
                            $treeNodeInterface.ImageIndex         = $iconDefinitions.Interface.Id
                            $treeNodeInterface.SelectedImageIndex = $iconDefinitions.Interface.Id
                            $treeNode.Nodes.Add($treeNodeInterface) | Out-Null
                        }
                    }
                    else
                    {
                        # Create a stub type node with only the type name
                        $treeNode = [System.Windows.Forms.TreeNode]::new($Name)
                    }

                    $treeNode.ImageIndex         = $iconDefinitions.Class.Id
                    $treeNode.SelectedImageIndex = $iconDefinitions.Class.Id

                    $cacheTypeTreeNodes[$Name] = $treeNode
                }

                $Parent.Nodes.Add($treeNode) | Out-Null
            }

            <#
                .SYNOPSIS
                    Convert a method to a tree node and add it to the parent.
            #>

            function Add-TreeNodeMethod
            {
                [CmdletBinding()]
                param
                (
                    # The parent tree node.
                    [Parameter(Mandatory = $false)]
                    $Parent,

                    # The method to add as tree node.
                    [Parameter(Mandatory = $true)]
                    [System.Management.Automation.PSMethodInfo]
                    $Method
                )

                foreach ($methodOverloadDefinition in $Method.OverloadDefinitions)
                {
                    # Try to match the method definition to extract the return type and the definition itself.
                    if ($methodOverloadDefinition -match "^(?<ReturnType>.*) ((?<Interface>.*\.))?$($Method.Name)\((?<Parameter>.*)\);?$")
                    {
                        $treeNode = [System.Windows.Forms.TreeNode]::new(('{0}{1}({2})' -f $Matches['Interface'], $Method.Name, $Matches['Parameter']))

                        Add-TreeNodeType -Parent $treeNode -Name $Matches['ReturnType']
                    }
                    else
                    {
                        # No match of an method definition
                        Write-Verbose "[Show-Object] Method definition '$methodOverloadDefinition' was unexpected. Show the original method definition."

                        $treeNode = [System.Windows.Forms.TreeNode]::new($methodOverloadDefinition)
                    }

                    $treeNode.ImageIndex         = $iconDefinitions.Method.Id
                    $treeNode.SelectedImageIndex = $iconDefinitions.Method.Id

                    $Parent.Nodes.Add($treeNode) | Out-Null
                }
            }

            <#
                .SYNOPSIS
                    Convert a property to a tree node and add it to the parent.
            #>

            function Add-TreeNodeProperty
            {
                [CmdletBinding()]
                param
                (
                    # The parent tree node.
                    [Parameter(Mandatory = $false)]
                    $Parent,

                    # The event to add as tree node.
                    [Parameter(Mandatory = $true)]
                    [System.Management.Automation.PSPropertyInfo]
                    $Property
                )

                $treeNode = [System.Windows.Forms.TreeNode]::new(('{0} = {1}' -f $Property.Name, $Property.Value))

                $treeNodeDummy = [System.Windows.Forms.TreeNode]::new('')
                $treeNodeDummy.Tag = @($Property.Value)
                $treeNode.Nodes.Add($treeNodeDummy) | Out-Null

                $treeNode.ImageIndex         = $iconDefinitions.Property.Id
                $treeNode.SelectedImageIndex = $iconDefinitions.Property.Id

                $Parent.Nodes.Add($treeNode) | Out-Null
            }

            <#
                .SYNOPSIS
                    Convert an event to a tree node and add it to the parent.
            #>

            function Add-TreeNodeEvent
            {
                [CmdletBinding()]
                param
                (
                    # The parent tree node.
                    [Parameter(Mandatory = $false)]
                    $Parent,

                    # The event to add as tree node.
                    [Parameter(Mandatory = $true)]
                    [Microsoft.PowerShell.Commands.MemberDefinition]
                    $Event
                )

                # Try to match the event definition to extract the return type and the definition itself.
                if ($Event.Definition -match "^(?<ReturnType>.*) ((?<Interface>.*\.))?$($Event.Name)\((?<Parameter>.*)\);?$")
                {
                    $treeNode = [System.Windows.Forms.TreeNode]::new(('{0}{1}({2})' -f $Matches['Interface'], $Event.Name, $Matches['Parameter']))

                    Add-TreeNodeType -Parent $treeNode -Name $Matches['ReturnType']
                }
                else
                {
                    # No match of an event definition
                    Write-Warning "[Show-Object] Event definition '$($Event.Definition)' was unexpected. Show the original event definition."

                    $treeNode = [System.Windows.Forms.TreeNode]::new($Event.Definition)
                }

                $treeNode.ImageIndex         = $iconDefinitions.Event.Id
                $treeNode.SelectedImageIndex = $iconDefinitions.Event.Id

                $Parent.Nodes.Add($treeNode) | Out-Null
            }

            <#
                .SYNOPSIS
                    Resolve a type name to a runtime type object.
            #>

            function Resolve-Type
            {
                [CmdletBinding()]
                param
                (
                    # The type name to resolve.
                    [Parameter(Mandatory = $true)]
                    [System.String]
                    $TypeName
                )

                # Try to find a valid type directly by the full name.
                $type = [System.Type]::GetType($TypeName)

                # Fall back to the type accelerators if the type was not found.
                if ($null -eq $type)
                {
                    $typeAccelerators = [System.Management.Automation.PSObject].Assembly.GetType('System.Management.Automation.TypeAccelerators')::Get
                    if ($typeAccelerators.ContainsKey($TypeName))
                    {
                        $type = $typeAccelerators[$TypeName]
                    }
                }

                # Return the resolved type or show a warning, if the type was
                # not found.
                if ($null -ne $type)
                {
                    Write-Output $type
                }
                else
                {
                    Write-Verbose "[Show-Object] The assembly type '$TypeName' was not found."
                }
            }

            <#
                .SYNOPSIS
                    Resolve a type name to a simple type object used primary for
                    deciding the icon.
            #>

            function Resolve-SimpleType
            {
                [CmdletBinding()]
                param
                (
                    # The object to add as tree node.
                    [Parameter(Mandatory = $true)]
                    [AllowNull()]
                    [System.Object]
                    $Object
                )

                if ($null -eq $Object)
                {
                    Write-Output 'Null'
                }
                elseif ($Object -is [System.String] -or $Object -is [System.Char])
                {
                    Write-Output 'String'
                }
                elseif ($Object -is [System.Boolean])
                {
                    Write-Output 'Boolean'
                }
                elseif ($Object -is [System.Enum])
                {
                    Write-Output 'Enum'
                }
                elseif ($Object -is [System.DateTime] -or $Object -is [System.DateTimeKind] -or
                        $Object -is [System.DateTimeOffset] -or $Object -is [System.TimeSpan])
                {
                    Write-Output 'Date'
                }
                elseif ($Object -is [System.Byte] -or $Object -is [System.SByte] -or
                        $Object -is [System.Int16] -or $Object -is [System.UInt16] -or
                        $Object -is [System.Int32] -or $Object -is [System.UInt32] -or
                        $Object -is [System.Int64] -or $Object -is [System.UInt64] -or
                        $Object -is [System.Single] -or $Object -is [System.Double] -or $Object -is [System.Decimal])
                {
                    Write-Output 'Number'
                }
                else
                {
                    Write-Output 'Object'
                }
            }


            ##
            ## Render Main Form
            ##

            $treeViewIconList = [System.Windows.Forms.ImageList]::new()
            foreach ($iconDefinitionName in $iconDefinitions.Keys)
            {
                $treeViewIconList.Images.Add([System.Drawing.Image]::FromStream([System.IO.MemoryStream]::new($iconDefinitions[$iconDefinitionName].Data)))
            }

            $treeView = [System.Windows.Forms.TreeView]::new()
            $treeView.Size = [System.Drawing.Size]::new($mainFormWidth - 16 - (2 * $mainFormPadding), $mainFormHeight - 39 - (2 * $mainFormPadding))
            $treeView.Location = [System.Drawing.Point]::new($mainFormPadding, $mainFormPadding)
            $treeView.ImageList = $treeViewIconList
            $treeView.add_BeforeExpand({
                param ($EventSender, $TreeViewCancelEventArgs)
                # Check if we have a single dummy child node, which needs to be
                # replaced with the real children on demand.
                $treeNode = $TreeViewCancelEventArgs.Node
                if ($null -ne $treeNode -and $treeNode.Nodes.Count -eq 1 -and $treeNode.Nodes[0].Text -eq '' -and $null -ne $treeNode.Nodes[0].Tag)
                {
                    $objects = @($treeNode.Nodes[0].Tag)
                    $treeNode.Nodes.Clear()
                    foreach ($object in $objects)
                    {
                        Add-TreeNodeObject -Parent $treeNode -Object $object
                    }
                }
            })
            $treeView.add_KeyDown({
                param ($EventSender, $KeyEventArgs)
                if ($KeyEventArgs.KeyCode -eq 'C' -and $KeyEventArgs.Control)
                {
                    $mainForm.Close()
                }
            })

            foreach ($object in $objects)
            {
                Add-TreeNodeObject -Parent $treeView -Object $object
            }

            $mainForm = [System.Windows.Forms.Form]::new()
            $mainForm.Text = $Title
            $mainForm.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon([System.Diagnostics.Process]::GetCurrentProcess().Path)
            $mainForm.Size = [System.Drawing.Size]::new($mainFormWidth, $mainFormHeight)
            $mainForm.MaximizeBox = $false
            $mainForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle
            $mainForm.Controls.Add($treeView)
            $mainForm.ShowDialog() | Out-Null
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError($_)
        }
        finally
        {
            if ($null -ne $mainForm)
            {
                $mainForm.Dispose()
            }
        }
    }
}