#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use Tree::Simple;
use Tree::Simple::View::HTML;
use Data::TreeDumper;
use Win32::Process::Info;
use 5.010;
use feature qw(say);
############################################################
# Get Subprocesses
############################################################
my $pi = Win32::Process::Info->new();
my %sub_pids = $pi->Subprocesses();
remove_win32_subprocess_recursion(\%sub_pids);
add_win32_subprocess_root_entry(\%sub_pids);
# e.g. 'ROOT' => [204,5944,3824,0]
sub add_win32_subprocess_root_entry
{
my( $ref_subs ) = @_;
my @total_sub_pid_list;
for my $ref_sub_pid_list (values %$ref_subs)
{
for my $sub_pid (@$ref_sub_pid_list)
{
push(@total_sub_pid_list, $sub_pid);
}
}
my @root_pid_list;
for my $pid (keys %$ref_subs)
{
unless( $pid ~~ @total_sub_pid_list )
{
push(@root_pid_list, $pid);
}
}
$ref_subs->{'ROOT'} = [@root_pid_list];
}
# remove win32 subprocess recursions
# e.g. '0' => [0,4]
# --> '0' => [4]
sub remove_win32_subprocess_recursion
{
my( $ref_subs ) = @_;
while( my ($pid, $ref_sub_pid_list) = each %$ref_subs )
{
if( $pid ~~ $ref_sub_pid_list )
{
@$ref_sub_pid_list = grep(!/$pid/, @$ref_sub_pid_list);
}
}
}
############################################################
# Create Process Tree
############################################################
my $root_pid = 'ROOT';
my $pid_tree = Tree::Simple->new($root_pid, Tree::Simple->ROOT);
build_pid_tree($root_pid, $pid_tree);
$pid_tree->DESTROY();
sub build_pid_tree
{
my ($pid, $pid_tree) = @_;
if( scalar @{ $sub_pids{$pid} } == 0 )
{
return;
}
for my $item ( @{ $sub_pids{$pid} } )
{
build_pid_tree( $item, Tree::Simple->new($item, $pid_tree) );
}
}
############################################################
# TRAVERSE TREE
############################################################
print "Relevant Information:\n";
$pid_tree->traverse( \&print_tree );
print "\n";
sub print_tree
{
my ($tree) = @_;
print (("\t" x $tree->getDepth()), $tree->getNodeValue(), "\n");
}
############################################################
# View Tree (Data::TreeDumper)
############################################################
print "Unfiltered Tree:Simple tree:\n";
print DumpTree($pid_tree, 'Win32 Process Tree');
print "\n";
print "Filtered Tree::Simple tree:\n";
print DumpTree($pid_tree, 'Win32 Process Tree', FILTER => sub
{
my $s = shift;
if('Tree::Simple' eq ref $s)
{
# TODO
}
return(Data::TreeDumper::DefaultNodesToDisplay($s)) ;
});
####
print DumpTree($pid_tree, 'Win32 Process Tree', FILTER => sub
{
my $s = shift;
if('Tree::Simple' eq ref $s)
{
return( 'SCALAR', undef, $_{'node'} );
}
return(Data::TreeDumper::DefaultNodesToDisplay($s)) ;
});
####
Filtered Tree::Simple tree:
Win32 Process Tree blessed in 'Tree::Simple'
`- = undef [S1]