PowerShell – View Objects of Processes

email me

Screenshot

 

Code

$processName = "explorer.exe"

Set-StrictMode -Version 3

Add-Type -Assembly System.Windows.Forms

$inputObject = dir variable:\* -Exclude InputObject,Args |
    Where-Object {
        $_.Value -and
        ($_.Value.GetType() -eq $processName.GetType()) -and
        ($_.Value.GetHashCode() -eq $processName.GetHashCode())
}

$inputObject = $inputObject| % Name | Select -First 1

if(-not $inputObject)
{
    $inputObject = "InputObject"
}

function PopulateNode($node, $object)
{
    if(-not $object) { return }

    if([System.Management.Automation.LanguagePrimitives]::GetEnumerator($object))
    {
 
        $count = 0

        $isOnlyEnumerable = $object.GetHashCode() -eq $object[0].GetHashCode()
        

        foreach($childObjectValue in $object)
        {            
            $newChildNode = New-Object Windows.Forms.TreeNode
            $newChildNode.Text = "$($node.Name)[$count] = $childObjectValue : " + $childObjectValue.GetType()
                     
            if($isOnlyEnumerable)
            {
                $newChildNode.Name = "@"
            }

            $newChildNode.Name += "[$count]"
            $null = $node.Nodes.Add($newChildNode)               
                        
            AddPlaceholderIfRequired $newChildNode $childObjectValue

            $count++
        }
    }
    else
    {
        
        foreach($child in $object.PSObject.Properties)
        {
        
            $childObject = $child.Value
            $childObjectType = $null
            if($childObject)
            {
                $childObjectType = $childObject.GetType()
            }

            $childNode = New-Object Windows.Forms.TreeNode
            $childNode.Text = $child.Name + " = $childObject : $childObjectType"
            $childNode.Name = $child.Name
            $null = $node.Nodes.Add($childNode)

            AddPlaceholderIfRequired $childNode $childObject
        }
    }
}

function AddPlaceholderIfRequired($node, $object)
{
    if(-not $object) { return }

    if([System.Management.Automation.LanguagePrimitives]::GetEnumerator($object) -or
        @($object.PSObject.Properties))
    {
        $null = $node.Nodes.Add( (New-Object Windows.Forms.TreeNode "...") )
    }
}

function OnAfterSelect
{
    param($Sender, $processTreeEventArgs)

    $nodeSelected = $Sender.SelectedNode

    $nodePath = GetPathForNode $nodeSelected

    $resultObject = Invoke-Expression $nodePath
    $output.Text = $nodePath

    if($resultObject)
    {
        $members = Get-Member -InputObject $resultObject | Out-String       
        $output.Text += "`n" + $members
    }
}


function OnBeforeExpand
{
    param($Sender, $processTreeCancelEventArgs)

    $selectedNode = $processTreeCancelEventArgs.Node

    if($selectedNode.FirstNode -and
        ($selectedNode.FirstNode.Text -eq "..."))
    {
        $selectedNode.Nodes.Clear()
    }
    else
    {
        return
    }

    $nodePath = GetPathForNode $selectedNode 

    Invoke-Expression "`$resultObject = $nodePath"

    PopulateNode $selectedNode $resultObject
}

function OnKeyPress
{
    param($Sender, $KeyPressEventArgs)

    if($KeyPressEventArgs.KeyChar -eq 3)
    {
        $KeyPressEventArgs.Handled = $true

        $node = $Sender.SelectedNode
        $nodePath = GetPathForNode $node
        [System.Windows.Forms.Clipboard]::SetText($nodePath)

        $winform.Close()
    }
}

function GetPathForNode
{
    param($Node)

    $nodeElements = @()

    while($Node)
    {
        $nodeElements = ,$Node + $nodeElements
        $Node = $Node.Parent
    }

    $nodePath = ""
    foreach($Node in $nodeElements)
    {
        $nodeName = $Node.Name

        if($nodeName.StartsWith('@'))
        {
            $nodeName = $nodeName.Substring(1)
            $nodePath = "@(" + $nodePath + ")"
        }
        elseif($nodeName.StartsWith('['))
        {

        }
        elseif($nodePath)
        {
            $nodePath += "."
        }

        $nodePath += $nodeName
    }

    $nodePath
}

$processTree = New-Object Windows.Forms.TreeView
$processTree.Dock = "Top"
$processTree.Height = 200
$processTree.PathSeparator = "."
$processTree.Add_AfterSelect( { OnAfterSelect @args } )
$processTree.Add_BeforeExpand( { OnBeforeExpand @args } )
$processTree.Add_KeyPress( { OnKeyPress @args } )

$output = New-Object System.Windows.Forms.TextBox
$output.Multiline = $true
$output.ScrollBars = "Vertical"
$output.Font = "Calibri"
$output.Dock = "Top"
$output.Height = 600

$root = New-Object Windows.Forms.TreeNode
$root.Text = "$processName : " + $processName.GetType()
$root.Name = '$' + $inputObject
$root.Expand()
$null = $processTree.Nodes.Add($root)

PopulateNode $root $processName

$winform = New-Object Windows.Forms.Form
$winform.Text = "Browsing " + $root.Text
$winform.Width = 1100
$winform.Height = 800
$winform.Controls.Add($output)
$winform.Controls.Add($processTree)
$null = $winform.ShowDialog()
$winform.Dispose()