Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

A killall for Windows

by Dog and Pony (Priest)
on Jun 04, 2002 at 13:55 UTC ( [id://171477]=sourcecode: print w/replies, xml ) Need Help??
Category: Win32 Stuff
Author/Contact Info /msg [Dog and Pony]
Description: Plain and simple, it is a variant of the killall script that can be found on some *NIX flavours - basically, you give it one or several names of processes (like 'calc', 'wordpad' or whatever has gone south atm), and it kills them. (No, it is no exact clone).

I have only had the possibility to try this out on Windows 2000, so i don't know if it will work on other flavours. I kinda suspect that it relies a bit on features that is NT only, which would mean NT, 2k and XP. So feedback is appreciated. :)

"Why not use the taskmanager?", I hear you ask. Because when something has gone really bad (lots of CPU), it is a pain to bring it up, scroll the list and try to click on and kill the process gone bad. In at least my case I almost always have a few DOS windows up, and usually know the process gone bad. Or one could type it in the Run menu too, more easy at least. And, of course there are plenty other uses if one rips the code and modifys it. :)

#!/usr/bin/perl -w

use strict;
use Win32::PerfLib;
use Win32::Process;
use Getopt::Std;
use vars qw($opt_d);

#################
#
# killall.pl 
# 
# kill all processes by a certain name
# on windows.
# 
# Run program without parameters
# for usage.
#

&print_usage() unless @ARGV;


# Get all process IDs by name.
my %process_by_name = &get_processes;

# Dump all available processes if -d :
getopts('d');
if($opt_d)
{
    print join "\n", sort keys %process_by_name;    
    exit;
}


# Sort through command line names:
foreach my $doomed (@ARGV)
{
    # Sort out matching processes:
    my @process_id = (map { /^$doomed$/i ? @{$process_by_name{$_}} : (
+) } keys %process_by_name); 
    
    if(!@process_id)
    {
        print "$doomed: no process killed\n";
        next;
    }

    # Blam! Take that, you lowly process you!    
    Win32::Process::KillProcess($_, 0) foreach(@process_id);
}

# Retrieves all process ID:s, sorted by name.
# Only slightly modified code from the 
# Win32::PerfLib manpage, actually.
sub get_processes
{
    my (%counter, %r_counter, %process_by_name);
    
    Win32::PerfLib::GetCounterNames('', \%counter);
    
    %r_counter = reverse %counter;

    # Get id for the process object
    my $process_obj = $r_counter{'Process'};
    # Get id for the process ID counter
    my $process_id = $r_counter{'ID Process'};
    
    # create connection to local computer
    my $perflib = new Win32::PerfLib('');
    my $proc_ref = {};
    
    # get the performance data for the process object
    $perflib->GetObjectList($process_obj, $proc_ref);
    $perflib->Close();
    
    my $instance_ref = $proc_ref->{'Objects'}->{$process_obj}->{'Insta
+nces'};

    foreach my $instance (values %{$instance_ref})
    {
        my $counter_ref = $instance->{'Counters'};
        foreach my $counter (values %{$counter_ref})
        {
            if($counter->{'CounterNameTitleIndex'} == $process_id)
            {
                # Process ID:s stored by name, in anonymous array:
                push @{$process_by_name{$instance->{'Name'}}}, $counte
+r->{'Counter'};
            }
        }
    }
    return %process_by_name;
}


sub print_usage
{
    print <<"USAGE";
 
Usage: $0 file [file_2...file_n]
       $0 -d
       
Filenames are caseinsensitive, but 
must otherwise have all letters. So
if the process is named 'CMD', you can
whack it with 'CMD', 'cmd', or 'CmD'
for instance. However, you will not
whack 'WINCMD32' this way (a good thing).

In the *NIX tradition, when all goes well,
the program keeps quiet. It is when it
speaks, something is wrong. :)

The -d option dumps all the names that
are available, if you don't know the exact
name of the process you want to whack.


USAGE
exit;
}
Replies are listed 'Best First'.
Re: A killall for Windows
by Mr. Muskrat (Canon) on Jun 04, 2002 at 15:04 UTC
    Even though you warned that it would probably only work on NT flavors of Windows, I gave it run through in Win98. When run with no arguments, it displays the usage imformation as expected. When run with the -d command line option, it silently fails. When run with a process name, it will display the process name followed by a colon and the text "no process killed".

    Who says that programmers can't work in the Marketing Department?
    Or is that who says that Marketing people can't program?
      That would be a natural behaviour, I guess. What happens (judging by the sound of it), is that it finds no processes in the process list, probably because it tries to find NT processes. :)

      Maybe should patch it up to croak on no processes returned (that would never be able to happen on a "supported" platform).

      Thanks for the help!


      You have moved into a dark place.
      It is pitch black. You are likely to be eaten by a grue.
        I tried this on an XP box and while it did return "no process killed" it did kill the process that I passed it. So not sure what is going on there. Pretty cool gizmo I like it -

        jschmitz
Re: A killall for Windows
by BlueBlazerRegular (Friar) on Jun 04, 2002 at 14:40 UTC

    ++ Dog and Pony. While I probably won't use this that much, it is nice to have it available and it's yet another example on how to interact with windows.

    By the way, this seems to work fine on NT.


    Pat
Re: A killall for Windows
by Pedro Picasso (Sexton) on Jun 07, 2002 at 14:32 UTC

    This is great code. I'm always looking for solutions to annoying Windows problems. I've also found a windows executable that does about the same thing. It allows you to select the processes you don't want to kill, and take out all the rest. I use it while playing processor/bandwidth intensive games. It's called EndItAll, and while it's not Perl, it does get the job done.


    -the Pedro Picasso
    (sourceCode == freeSpeech)
Re: A killall for Windows
by Anonymous Monk on Dec 08, 2004 at 11:36 UTC
    Thanks. It is a very useful script. In addition to it being quicker than task manager, it can be run from other programs, Perl scripts & batch file much easier than the GUI Taskmanager.
Re: A killall for Windows
by wolfger (Deacon) on Aug 17, 2004 at 14:12 UTC
    I am running Win2K here at work, and this doesn't work for me. Running without args gives me the usage. Running with -d shows me nothing. Running with a process name yields "<process name>: no process killed". I would love it if I could get this to work. I would love it more if my company would switch to *nix...

    --
    Believe nothing, no matter where you read it, or who said it - even if I have said it - unless it agrees with your own reason and your own common sense.
    (Buddha)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://171477]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (5)
As of 2024-04-16 04:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found