mikejones has asked for the wisdom of the Perl Monks concerning the following question:

In the following code I am printing all processes's CPU and RAM usage, however I only want this data for a certain few processes. For example instead of seeing in my output:
__DATA__ Name => ---- SymSPort.exe WorkingSetSize => -------------- 348160 KernelModeTime => -------------- 0.0625 UserModeTime => ------------ 0.046875 Name => ---- uphclean.exe WorkingSetSize => -------------- 155648 KernelModeTime => -------------- 0.03125 UserModeTime => ------------ 0.03125 ... ... ... and another proccess name and another process name....
I only want to see this data for a selected few process names; can we say grep? Tried an HoA, but the output was all garbbled together. Any ideas? thank you
use strict; use warnings; use Win32::Process::Info; use Data::Dumper; my $pio_2 = Win32::Process::Info->new (); my @pids = $pio_2->ListPids (); my @proc_info; for my $pid (@pids) { @proc_info = $pio_2->GetProcInfo($pid); for my $info (@proc_info) { for my $key (keys %{$info}) { if ($key eq 'Name' or $key eq 'WorkingSetSize' or $key eq 'UserModeTime' or $key eq 'KernelModeTime') { my $value = ${$info}{$key}; print qq(\n$key => \n), q(-) x length $key, qq(\n$value \n); } ## END IF } } }

Replies are listed 'Best First'.
Re: Win32... CPU/RAM usage
by BrowserUk (Patriarch) on Jul 05, 2007 at 20:51 UTC

    Something like this?

    See the { no_user_info => 1 } parmeter on the GetProcInfo() call. If you don't need user information, gathering it slows things down horribly. (Also, notice the lc inside the grep.)

    #! perl -slw use strict; use warnings; use Win32::Process::Info; use Data::Dumper; my $pio_2 = Win32::Process::Info->new (); my @pids = $pio_2->ListPids (); my @proc_info; my %ofInterest = map { $_ => 1 } qw[ perl.exe cmd.exe textpad.exe ]; my @fields = qw[ Name WorkingSetSize UserModeTime KernelModeTime ]; printf "%-25s %-14s %-12s %-14s\n", @fields; for my $pid (@pids) { @proc_info = $pio_2->GetProcInfo( { no_user_info => 1 }, $pid); for my $info ( grep{ exists $ofInterest{ lc $_->{ Name } } } @proc_info ) { printf "%-25s %14d %12.6f %14.7f\n", @{ $info }{ @fields }; } } __END__ C:\test>junk4 Name WorkingSetSize UserModeTime KernelModeTime CMD.EXE 1605632 2.328125 5.5156250 CMD.EXE 36864 0.015625 0.4218750 TextPad.exe 6189056 215.453125 108.9843750 CMD.EXE 65536 0.015625 0.2812500 perl.exe 7122944 0.375000 0.2187500

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Will you explain the line b/c I get lost at the lc part
      grep{ exists $ofInterest{ lc $_->{ Name } } } @proc_info ## : )
      Ahh heck just explain the entire embedded for loop:
      for my $info ( grep{ exists $ProcsOfInterest{ lc $_->{ Name } } } @proc_info ) { printf "%-25s %14d %12.6f %14.7f\n", @{ $info }{ @fields }; }

        Sure, NP.

        As you know, GetProcInfo() returns an array of hashes--1 hash per running process. One of the keys in those hashes is the Name of the executable. To avoid processing those processes you are not interest in, I used grep to check each of the return process names against the hash %ofInterest and only let it through if it exists.

        The list of processes that you are interested in is in that hash:

        my %ofInterest = map { $_ => 1 } qw[ perl.exe cmd.exe textpad.exe ];

        Rather than try and get the case of the program names correct--for the three in my example that would be perl.exe, CMD.EXE, TextPad.exe--, I typed them all in lower case and the used lc to lowercase the names return from the system to ensure they matched those I put in the hash.

        So now the for loop body will only be entered for those processes you are interest in. All that is left is to extract the four fields of each of those hashes that you are interested in. I placed the names of those four fields in an array:

        my @fields = qw[ Name WorkingSetSize UserModeTime KernelModeTime ];

        So now I can use a hash slice (see perlreftut for info on hash references and hash slices and much more), to extract the values you want and supply them to printf for display:

        for my $info ( # This ^^^^^ var will be set to the hashref each of the ... grep{ exists $ProcsOfInterest{ lc $_->{ Name } } } @proc_info # ...............^^^^^^^^^^^^^^^^ processes of interest ) { # ........................and is used here vvvvv printf "%-25s %14d %12.6f %14.7f\n", @{ $info }{ @fields }; # .......................in a hash slice ^^ ^^ ^ # ............................with the field names ^^^^^^^ # ..to produce the wanted 4 values and supply them to printf }

        The hash slice

        my @fields = qw[ Name WorkingSetSize UserModeTime KernelModeTime ]; ... printf ... @{ $info }{ @fields };

        is equivalent to:

        printf ... @{ $info }{'Name','WorkingSetSize','UserModeTime','KernelMo +deTime'};

        is equivalent to:

        printf ... $info->{ Name }, $info->{ WorkingSetSize }, $info->{ UserModeTime }, $info->{ KernelModeTime };

        Does that help?


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re:Win32... CPU/RAM usage
by johngg (Canon) on Jul 05, 2007 at 19:51 UTC
    Rather than going through all of the keys and testing for what you want perhaps you could just access those you want directly. Not tested as I use *nix mostly.

    my @wantedInfoTypes = qw{ Name WorkingSetSize UserModeTime KernelModeTime}; ... for my $infoType ( @wantedInfoTypes ) { print qq{\n$infoType => \n}, q{-} x length $infoType, qq{\n$info->{$infoType}\n}; } ...

    I hope this is of use.

    Cheers,

    JohnGG

    Update: NetWallah's output shows that I missed a newline in the print statement which I've now corrected :)

      I see your point, however I do want the flexibility in getting all information for all PIDS, but also want the ability to grab certain strings on demand. So my question still remains open for help! I liked you print block and will use that!
        One way to keep that flexibility would be to use something like Getopt::Long so that you could specify multiple items of interest on the command line which would populate an array. (Best to have a look at the documentation for Getopt::Long as I don't have an example to hand.) Then from the array create a compiled regular expression using the pipe symbol for alternation to use in the grep. If you didn't specify anything on the command line the array would be empty so in that case push (or unshift a . (dot) onto the array so the regex would match anything.

        use strict; use warnings; use Getopt::Long; my @wanted = (); GetOptions(q{want=s}, \@wanted); push @wanted, q{.} unless @wanted; my $rxWanted; { local $" = q{|}; $rxWanted = qr{@wanted}; } ... for my $key ( grep { m{$rxWanted} } keys %$info } { ... }

        Again, not tested but I think the concept is sound.

        Cheers,

        JohnGG

Re: Win32... CPU/RAM usage
by NetWallah (Canon) on Jul 05, 2007 at 20:57 UTC
    This code incorporates johngg's idea, and adds code-file-name based "grep".
    use strict; use warnings; use Win32::Process::Info; use Data::Dumper; my $pio_2 = Win32::Process::Info->new (); my @pids = $pio_2->ListPids (); my @proc_info; my @wantedInfoTypes = qw{ Name WorkingSetSize UserModeTime KernelModeTime }; my @InterestingExecutables = qw{ VISIO.exe cmd.exe notepad.exe skype.exe GoogleDesktop.exe wmplayer.exe }; for my $pid (@pids) { @proc_info = $pio_2->GetProcInfo($pid); for my $info (@proc_info) { grep /$info->{Name}/i, @InterestingExecutables or next; for my $infoType ( @wantedInfoTypes ) { print qq{\n$infoType => \n}, q{-} x length $infoType, qq{$info->{$infoType}\n}; } } }
    Output:
    Name => ----GoogleDesktop.exe WorkingSetSize => --------------7118848 UserModeTime => ------------90.5117802 KernelModeTime => --------------149.3085571 Name => ----GoogleDesktop.exe WorkingSetSize => --------------3760128 UserModeTime => ------------62.3379996 KernelModeTime => --------------115.8931429 Name => ----wmplayer.exe WorkingSetSize => --------------45211648 UserModeTime => ------------87.5009609 KernelModeTime => --------------72.3532638 Name => ----GoogleDesktop.exe WorkingSetSize => --------------7290880 UserModeTime => ------------367.5071558 KernelModeTime => --------------239.1651331 Name => ----Skype.exe WorkingSetSize => --------------45948928 UserModeTime => ------------3.8376246 KernelModeTime => --------------2.7144174 Name => ----VISIO.EXE WorkingSetSize => --------------56135680 --snip---
    Note - there ARE INDEED multiple instances of googledesktop running on my PC.

    Update:Ignore my hack - BrowserUk (++) posted much better code while I was hacking.

         "An undefined problem has an infinite number of solutions." - Robert A. Humphrey         "If you're not part of the solution, you're part of the precipitate." - Henry J. Tillman

      Wow! Thanks to all for these great examples and ideas. Kudos to all!