A perl script to list all the current running processes / a particular process on an array of systems. Needs Windows Management and
Instrumentation Service Enabled on the remote machine. Tested on Active
Perl 5.6+ and XP. Useful for maintaining inventory information. Usefull to find an instance of say a suspicious process on all ur systems on the network.
use strict;
use Win32::OLE(‘in’);
use constant wbemFlagReturnImmediately => 0×10;
use constant wbemFlagForwardOnly => 0×20;
my @computers = (“localhost”);
foreach my $computer (@computers) {
print “\n”;
print “————————————————————\n”;
print “| Computer: $computer | \n”;
print “————————————————————\n”;
my $objWMIService = Win32::OLE->GetObject(“winmgmts:\\\\$computer\\root\\CIMV2″) or die “WMI connection failed.\n”;
my $colItems = $objWMIService->ExecQuery(“SELECT * FROM Win32_Process”, “WQL”,
wbemFlagReturnImmediately | wbemFlagForwardOnly);
foreach my $objItem (in $colItems) {
print “Caption: $objItem->{Caption}\n”;
print “CommandLine: $objItem->{CommandLine}\n”;
print “CreationClassName: $objItem->{CreationClassName}\n”;
print “CreationDate: $objItem->{CreationDate}\n”;
print “CSCreationClassName: $objItem->{CSCreationClassName}\n”;
print “CSName: $objItem->{CSName}\n”;
print “Description: $objItem->{Description}\n”;
print “ExecutablePath: $objItem->{ExecutablePath}\n”;
print “ExecutionState: $objItem->{ExecutionState}\n”;
print “Handle: $objItem->{Handle}\n”;
print “HandleCount: $objItem->{HandleCount}\n”;
print “InstallDate: $objItem->{InstallDate}\n”;
print “KernelModeTime: $objItem->{KernelModeTime}\n”;
print “MaximumWorkingSetSize: $objItem->{MaximumWorkingSetSize}\n”;
print “MinimumWorkingSetSize: $objItem->{MinimumWorkingSetSize}\n”;
print “Name: $objItem->{Name}\n”;
print “OSCreationClassName: $objItem->{OSCreationClassName}\n”;
print “OSName: $objItem->{OSName}\n”;
print “OtherOperationCount: $objItem->{OtherOperationCount}\n”;
print “OtherTransferCount: $objItem->{OtherTransferCount}\n”;
print “PageFaults: $objItem->{PageFaults}\n”;
print “PageFileUsage: $objItem->{PageFileUsage}\n”;
print “ParentProcessId: $objItem->{ParentProcessId}\n”;
print “PeakPageFileUsage: $objItem->{PeakPageFileUsage}\n”;
print “PeakVirtualSize: $objItem->{PeakVirtualSize}\n”;
print “PeakWorkingSetSize: $objItem->{PeakWorkingSetSize}\n”;
print “Priority: $objItem->{Priority}\n”;
print “PrivatePageCount: $objItem->{PrivatePageCount}\n”;
print “ProcessId: $objItem->{ProcessId}\n”;
print “QuotaNonPagedPoolUsage: $objItem->{QuotaNonPagedPoolUsage}\n”;
print “QuotaPagedPoolUsage: $objItem->{QuotaPagedPoolUsage}\n”;
print “QuotaPeakNonPagedPoolUsage: $objItem->{QuotaPeakNonPagedPoolUsage}\n”;
print “QuotaPeakPagedPoolUsage: $objItem->{QuotaPeakPagedPoolUsage}\n”;
print “ReadOperationCount: $objItem->{ReadOperationCount}\n”;
print “ReadTransferCount: $objItem->{ReadTransferCount}\n”;
print “SessionId: $objItem->{SessionId}\n”;
print “Status: $objItem->{Status}\n”;
print “TerminationDate: $objItem->{TerminationDate}\n”;
print “ThreadCount: $objItem->{ThreadCount}\n”;
print “UserModeTime: $objItem->{UserModeTime}\n”;
print “VirtualSize: $objItem->{VirtualSize}\n”;
print “WindowsVersion: $objItem->{WindowsVersion}\n”;
print “WorkingSetSize: $objItem->{WorkingSetSize}\n”;
print “WriteOperationCount: $objItem->{WriteOperationCount}\n”;
print “WriteTransferCount: $objItem->{WriteTransferCount}\n”;
print “\n”;
}
}
Blogged with Flock











You might find something like the following useful… it abstracts away a lot of the hard-coding so that you can query ANY WMI class — not just the Win32_Process class — and you can query multiple classes in the same script very easily. Useful for tracking hardware, software, server metrics, and a lot more…
##################################################
#! perl\bin\perl -w
use strict;
use Win32::OLE(‘in’);
# supply a list of WMI classes to interrogate
my @requests = (‘Win32_Process’, );
# supply a list of computer systems to query
my @computers = (“$ENV{COMPUTERNAME}”, );
# Connect to each system’s CimV2 repository in turn.
for my $computer( @computers ){
my $wmi_repos = Win32::OLE->GetObject(“winmgmts:{impersonationLevel=impersonate}!\\\\$ENV{COMPUTERNAME}\\root\\CIMV2″)
or die “WMI connection failed: “.Win32::OLE->LastError().”\n”;
# Call to each desired Namespace in the current WMI repository.
for my $request( @requests ){
my $wmi_collection = $wmi_repos->ExecQuery(“SELECT * FROM $request”, “WQL”, 48 )
or die “WQL query failed: “.Win32::OLE->LastError().”\n”;
# For each member of the class, build a data-structure to hold its Methods and Properties.
for my $item (in $wmi_collection){
my @methods = join (“, “, map {$_->{Name}}( in $item->{Methods_} ) );
my %properties = map { $_->{Name} => $_->{Value} }( in $item->{Properties_} );
# Then format and print the results.
print “\n$computer :: $request :: $properties{Name}\n”, “\tMethods: @methods\n\tProperties:\n”;
for my $property( sort keys %properties ){
( $properties{$property} )
? print “\t\t$property = $properties{$property}\n”
: print “\t\t$property =\n”;
} } } }
##################################################
…one of Perl’s main advantages (and main disadvantages) is it’s terse syntax. If you just translate VBScripts to Perl you’ll lose alot of the advantages that have caused people to use Perl to begin with. Hope you find this example helpful!
By: Montgomery Conner on September 18, 2006
at 5:06 pm
EDIT: the following is a correction that enables an array of computer names to be used… replace $wmi_repos =…
Win32::OLE->GetObject(”winmgmts:
{impersonationLevel=impersonate}!\\\\$computer\\root\\CIMV2″)
or die “WMI connection failed: “.Win32::OLE->LastError().”\n”;
i.e. $ENV{COMPUTERNAME} –the local system–
needs to be replaced with the looping $computer variable in the WQL query portion of the script.
Sorry for any confusion.
By: Montgomery Conner on September 18, 2006
at 5:21 pm
Doesn’t work for me – I’ve checked that WMI service is running, tried both yours and Montgomery’s scripts (had to substitute non-ASCII characters after copying and pasting the above otherwise script wouldn’t compile).
No errors returned by the OLE methods (i.e. doesn’t bomb out at the die statements), but the list of processes appears to be empty and length of wmi_collection is -1… and when I try to use “print Dumper $wmi_collection” (after loading Data::Dumper module) I get an OLE exception and unspecified error and the contents of the wmi_collection hash appear as this:
$VAR1 = bless( {
‘Count’ => undef,
‘Security_’ => bless( {
‘ImpersonationLevel’ => 3,
‘AuthenticationLevel’ => 6,
‘Privileges’ => bless( {
‘Count’ => 0
}, ‘Win32::OLE’
)
}, ‘Win32::OLE’ )
}, ‘Win32::OLE’ );
Can someone for who this works post what they get out for:
print Dumper $wmi_collection;
so I can compare?
Thanks
By: Steve on October 2, 2006
at 12:12 pm
Steve,
Data::Dumper is going to have problems with full OLE collection objects if you need to peek at any real data. So, you probably need to insert a print statement in the loop-block with the individual member $item, like so:
for my $item ($wmi_collection){
…
print Dumper $item;
…
}
But, I have no idea why these scripts would be failing for you (and silently at that)… good luck.
BTW, you are running this against your local machine to test it, right? I’ve seen remote connections to WMI fail if ther’s port blocking or something like that…
By: Montgomery Conner on October 11, 2006
at 9:54 pm
I really need to learn to proof read before I post… that code should have been:
for my $item ( in $wmi_collection ){
…
The ‘in’ is win32::OLE’s collection magic…
By: Montgomery Conner on October 11, 2006
at 9:58 pm
use Win32::OLE qw( in );
use Win32::OLE::Variant;
use Win32::IPConfig;
use Socket ;
#Purpose to start remote process :Usage: perl filename.pl exe_to_run.exe
#usage : StartRemoteProcess 4FIL19273 changeSetting.exe IMMIDIATERUN 1
#RUNAS /profile /user:userName “StartRemoteProcess Workstation ExecutableName.exe Argument1 Argument2 ″ | sanur password
our $Machine = $ARGV[0];
our @ARGV = @ARGV[1..$#ARGV] ; #cut the host’s name from the command line
our $CLASS = “WinMgmts:{impersonationLevel=impersonate}!//$Machine”;
main();
sub main
{
getIpFromDomainName($Machine);
my $success = startProc();
my $counter = 0 ;
while ( $success == 0 && $counter C:/Temp/TEMP/$Machine.txt” ) or
die “cannot open $Machine.txt $! \n” ;
print FH “$Machine failed to execute command :\n” ;
foreach my $line (@ARGV)
{ chop($_);
print FH “$_ ” ;
}
close FH ;
}
}
sub getIpFromDomainName
{
my $host = shift ;
my $hostIp = () ; #the ip of the host we are going to return
my $address = gethostbyname(“$host”) ;
# print gethostbyname($_) , “\n” ;
print inet_ntoa($address) , “\n” ;
$hostIp = inet_ntoa($address) ;
return $hostIp ;
#eof sub getIpFromDomainName
}
sub startProc
{ #todo
my $hostIp = getIpFromDomainName($Machine);
$WMI = Win32::OLE-> GetObject( $CLASS ) || die “Unable to connect to
$Machine:” . Win32::OLE->lastError();
$PROCESSSTARTUP = $WMI-> Get(“Win32_ProcessStartup”)->SpawnInstance_;
$PROCESSSTARTUP-> {WinstationDesktop} = “winsta0\\default”;
$PROCESSSTARTUP-> {ShowWindow} = 1;
print “$PROCESSSTARTUP-> {WinstationDesktop}\n”;
$Process = $WMI-> Get( “Win32_Process” ) || die “Unable to get the
process list:” . Win32::OLE-> LastError();
$vPid = Variant( VT_I4 | VT_BYREF, 0 );
if( 0 == $Process-> Create( join( ” “, @ARGV ), undef,
$PROCESSSTARTUP, $vPid ) ) {
print “PID $vPid\n”;
sleep 2 ;
return 1 ;
}
else
{
print “Failed .\n”;
sleep 2 ;
return 0 ;
}
} #eof startProc
By: Yordan Georgiev on December 18, 2006
at 10:20 am
This was kind a out of the subject but hei it uses the same Win::OLE magic ..
By: Yordan Georgiev on December 18, 2006
at 10:21 am
Oh my god loved reading your article. I added your rss to my google reader.
By: HogeMaseWonna on November 25, 2009
at 1:35 am