#!/usr/bin/perl
# -*- Perl -*-

=begin comment

This code monitors programs running on other computers in the house.
Currently it is windows only, although it could be extended for unix.

Yes, this is evil Big Brother behavior, but it helps us parents
impose measurements on computer game usage.  For those with kids
hooked on todays amazing computer games, this is a good way to
encourage some healthy, non-fun activity in cases where, left 
unchecked, children only emerge from their gaming dungens for 
periodic food supplies.   Nothing like the smell of a freshly
mowed lawn the morning before an Everquest raid (grin).

Related code is in mh/code/bruce/monitor_router.pl, where we can
track packets going to and from the internet.

This code requires Microsoft WMI to be installed.  More info here:
  http://msdn.microsoft.com/downloads/sdks/wmi
  http://www.microsoft.com/technet/win2000/mngwmi.asp?a=printable
  http://msdn.microsoft.com/library/default.asp?URL=/library/psdk/wmisdk/clascomp_3d4j.htm

WMI is a bit tricky to get running.  Here are some tips:
  - Use the same userid and password on all boxes.

SMI is already installed on Windows 2000.  For Win95/98, follow this tips:
  - Change from share-level to user-level access (under file share menu)
  - run wmi9x.exe (from msdn sdks/wmi url above)
  - run WIN98\system\WBEM\WinMgmt.exe and turn on auto-restart
  - run win98\system\dcomcnfg.exe  (not sure if we need access boxes filled/checked)

# - set HOUSE 'Local security settings -> local policies -> user rights asscgnements -> Network & Authenticated users (??)

Author:  Bruce Winter bruce@misterhouse.net
URL:     http://misterhouse.net/mh/bin/find_win_programs

This free software is licensed under the terms of the GNU public license. 
Copyright 1998-2001 Bruce Winter

=cut

use strict;

my($Pgm_Path, $Pgm_Name, $Version);
BEGIN {
    ($Version) = q$Revision: 1.1 $ =~ /: (\S+)/; # Note: revision number is auto-updated by cvs
    ($Pgm_Path, $Pgm_Name) = $0 =~ /(.*)[\\\/](.+)\.?/;
    ($Pgm_Name) = $0 =~ /([^.]+)/, $Pgm_Path = '.' unless $Pgm_Name;
}

my %parms;
use Getopt::Long;
if (!&GetOptions(\%parms, 'h', 'help', 'all') or
    !@ARGV or $parms{h} or $parms{help}) {
    print<<eof;

$Pgm_Name finds programs running on networked Windows computers.

Requires WMI to be installed on both/all computers.

  Version: $Version

  Usage:
   $Pgm_Name [options] box_list [search_string]

    box_list is a comma delimited list of boxes to search
    search_string lists only programs that match 

   options:
    -h or -help  => This help text
    -all         => Show/search all programs

  Examples:
    $Pgm_Name house
    $Pgm_Name "house,dm,c2" quake
    $Pgm_Name -all "house,dm,c2"

eof
    exit;
}

use Win32::OLE;

my @boxes = split ',', shift;
my $find  = shift;

for my $box (@boxes) {
    print "\nFinding programs on $box\n";
    my ($count, $results) = &wmi_processes($box);
    print "  Total processes: $count\n$results";
}

sub wmi_processes {
    my ($box) = @_;
    my $list;
                                # Ignore common WIN98 and win2000 processes
    my @ignore_list = qw(DDHELP EXPLORE HPSJVXD .DLL MPREXE MSTASK
                         REXPROXY RPCSS RSRCMTR STIMON SYSTRAY TASKMON WINMGMT
                         cmd csrss 4nt explore lsass mstask mgsys services spool smss svchost svcjpst system
                         taskmgr winmgmt regsvc system winlogon
                         defwatch rtvscan stisvc vptray OSA msgsys mgabg pdesk);

    my $count = 0;
    if(my $WMI = Win32::OLE->GetObject("WinMgmts:{impersonationLevel=impersonate}!//$box")) {
        for my $process (Win32::OLE::in($WMI->InstancesOf('Win32_Process'))) {
            my $name = $process->{Name};
            $count++;
            next if !$parms{all} and grep $name =~ /$_/i, @ignore_list;
            next if $find and $name !~ /$find/i;
            $list .= sprintf " PID:%5d,%5d Pgm:%-15s Threads:%3s Mem:%6.2f,%6.2f Date: %s\n",
            $process->{ProcessID}, $process->{ParentProcessID}, $process->{Name}, $process->{ThreadCount}, 
            $process->{WorkingSetSize}/10**6, $process->{PeakWorkingSetSize}/10**6, $process->{CreationDate};
        }
    }
    else {
        print "WMI unable to connect to \\$box:" . Win32::OLE->LastError() . "\n";
    }
    return($count, $list);
}


#
# $Log: find_programs,v $
# Revision 1.1  2001/05/28 21:22:46  winter
# - 2.52 release
#
#
