Link to home
Start Free TrialLog in
Avatar of allio
allio

asked on

Killing Exes running from a delphi application

Hi there
  Can You kill Exes from delphi? Like Microsoft word or internet explorer or games running like Half life, red alert etc.

If so how do you do this?

thanks so much !!!!!
Avatar of kretzschmar
kretzschmar
Flag of Germany image

yes, multiple possibilities
Avatar of geobul
geobul

Hi,

procedure TForm1.Button2Click(Sender: TObject);
var
 H : HWND;
begin
 H := FindWindow('notepad', nil);
 if IsWindow(H) then
   PostMessage(H, WM_CLOSE, 0, 0);
end;

Regards, Geo

Avatar of allio

ASKER

what if it does not have a window? but the exe is still running in the windows processes? how can you kill it?
Avatar of allio

ASKER

what if it does not have a window? but the exe is still running in the windows processes? how can you kill it?
for IE: H := FindWindow('IEFrame', nil);
for MSWord: H := FindWindow('OpusApp', nil);
SOLUTION
Avatar of geobul
geobul

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of allio

ASKER

how do you get the PID?
Avatar of allio

ASKER

how do you get the PID?
What do you know about the app you are about to kill? What Windows versions should the code work on?
look at www.madshi.net
there is all what you need

or wait until madshi joins this q
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;


implementation

{$R *.DFM}


var s:Tstringlist;


procedure TForm1.Button1Click(Sender: TObject);


function EnumWindowsProc(hwnd : HWND ;lParam : longint):boolean;stdcall;
var
  wn : array[0..255] of char;
  pid: THandle;
  w : string;
begin
  if hwnd <> 0 then
  begin
    GetWindowThreadProcessId(hwnd, @pid);
    // filter out if this is our application window
    // and all child windows
    if {(pid <> GetCurrentProcessId) and }(GetParent(hwnd)= 0) then
    begin
      // get the caption
      // or use the commented IF to get application names
      if GetWindowText(hwnd, wn,sizeof(wn)) <> 0 then
//    if GetModuleFileName(GetWindowLong(hwnd,GWL_HINSTANCE),wn,sizeof(wn)) <> 0 then
      begin{}
        w:= Format('%6d ',[pid])+StrPas(wn);
        S.Add(w);
      end;{}
   end;
    result := true;
  end else result := false;
end;

begin
  try
   S := TStringList.Create;
   S.Sorted := true;
   S.Duplicates := dupIgnore;
   ListBox1.Items.Clear;
   S.Clear;
   EnumWindows(@EnumWindowsProc,0);
   ListBox1.Items.AddStrings(S);
  finally
    S.Free;
  end;
end;

end.

now implement geobul's code.
just open a notepad..
now check for it's pid...
and kill... hahahaha (not really)

so who will get points? me or geobull or will allio be so nice and make a ask a new question with points for xxx?
xxx := kretzschmar
:-)))
I hate to pop anyone bubble here, but there is a slight snag with this question: To kill a process in Windows you need to get the pid (as already mentioned)... the snag come in actually getting that PID. In Windows 9x you have to use one API which doesn't work in NT/2000, and of course in NT/2000 you have to use another API. So, the first order of business HAS to be determing the operating system, then calling the appropriate function to enumerate the open processses and THEN killing the one you want. I have code for this archived OR you could just use my TEnumProcs component. You can get a demo application using it from my site:

http://www.drdelphi.com/delphi/right/comp.html


Good luck!!
really I didn't know could you elaborate since:

EnumWindows

Requirements
  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.

source:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/windows_9v6r.asp
The EnumWindows function enumerates all top-level windows on the screen by passing the handle of each window, in turn, to an application-defined callback function. EnumWindows continues until the last top-level window is enumerated or the callback function returns FALSE.

This does nothing for windowsless (console) applications, nor does it give you the ProcessId. It'll only give you the handles for the WINDOWS that are open.

Hope this clears it up for you.


DrDelphi
just to repost

look at www.madshi.net
there is all what you need

enumerates processes,
is win-version independent
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Give me your address to send you a sample project that return a list of all running processes and give you the oportunity to close the wished applications.

Regards,
Nick
Give me your address to send you a sample project that return a list of all running processes and give you the oportunity to close the wished applications.

Regards,
Nick
Give me your address to send you a sample project that return a list of all running processes and give you the oportunity to close the wished applications.

Regards,
Nick
Ginsonic,
  You can get that from my site... see above.

Good luck!!
HI,
Use the following (seems it is not mentioned yet):
CreateToolhelp32Snapshot,
Process32First,
Process32Next,
OpenProcess,
TerminateProcess.
Sincerely,
Nestorua.
DrDelphi , I see that your component isn't freeware .
And my sample project don't use any component to do this job .
I remember that in past I answered here at Ex-Ex to a similar question and the asker was happy with my solution .
a very old sample from my paq,
works only for win9x-versions,
(not tested for me,xp, but works not for nt, 2000)
it is not exact what you need

--- paste begin
here is a sample which stores processes with windows in a treeview
the windowhandle is stored in the data-option


     unit enumw2_u;

     interface

     uses
       Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
       StdCtrls, tlhelp32, ComCtrls;

     type
       TForm1 = class(TForm)
         Button1: TButton;
         TreeView1: TTreeView;
         Edit1: TEdit;
         procedure Button1Click(Sender: TObject);
         procedure TreeView1Click(Sender: TObject);
         procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
       private
         Procedure GetThreads(ProcessID : DWord);
         Procedure GetProcesslist;
         { Private-Deklarationen }
       public
         { Public-Deklarationen }
       end;

     var
       Form1: TForm1;

     implementation

     {$R *.DFM}

     Var
       WNode2: TTreeNode = Nil; {intern Global defined for multiple use}
       WNode : TTreeNode = Nil; {intern Global defined for multiple use}
       WName : Array[0..100] of char;
       TheWinHandle : THandle = 0; {intern Global defined for intern global Access}

     Function TWCallBack(H : THandle; V : Longint) : longBool; stdcall;
     begin
       if GetParent(H) = 0 then
       begin
         GetwindowText(H,@WName[0],100);
         WNode2 := Form1.TreeView1.Items.AddChild(WNode,StrPas(@WName[0]));
         WNode2.Data := Ptr(H); {Store the Handle in the DataOption}
       end;
       Result := True;
     end;

     Procedure TForm1.GetThreads(ProcessID : DWord);
     var
       ThreadEntry32 : TThreadEntry32; {Defined in TlHelp32}
       TLHandle : THandle;
     begin
       TLHandle := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
       if Thread32First(TLHandle,ThreadEntry32) then
       begin
         if ThreadEntry32.th32OwnerProcessID = ProcessID then
           EnumThreadWindows(ThreadEntry32.th32ThreadID,@TWCallBack,0);
         while Thread32Next(TLHandle,ThreadEntry32) do
           if ThreadEntry32.th32OwnerProcessID = ProcessID then
             EnumThreadWindows(ThreadEntry32.th32ThreadID,@TWCallBack,0);
       end;
       CloseHandle(TLHandle);
     end;

     Procedure TForm1.GetProcesslist;
     var
       PLHandle : Thandle;
       ProcessEntry32 : TProcessEntry32; {Defined in TlHelp32}
     begin
       PLHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
       if Process32First(PLHandle,ProcessEntry32) then
       begin
         Wnode := TreeView1.Items.Add(Nil,strPas(@ProcessEntry32.szExeFile[0]));
         GetThreads(ProcessEntry32.th32ProcessID);
         while Process32Next(PLHandle,ProcessEntry32) do
         begin
           Wnode := TreeView1.Items.Add(Nil,strPas(@ProcessEntry32.szExeFile[0]));
           GetThreads(ProcessEntry32.th32ProcessID);
         end;
       end;
       CloseHandle(PLHandle);
     end;

     Procedure CleanUpTree(Nodes : TTreeNodes);
     begin
       {CleanUp Windows without Text (most Controls)}
       WNode := Nodes.GetFirstNode;
       While WNode <> Nil do
       begin
         If WNode.Text = '' then
         begin
           WNode2 := WNode.Getnext;
           WNode.Delete;
           WNode := WNode2;
         end
         else
           WNode := WNode.GetNext;
       end;
       {CleanUp Processes with no windows}
       WNode := Nodes.GetFirstNode;
       While WNode <> Nil do
       begin
         If (WNode.Parent = Nil) and (WNode.GetFirstChild = Nil) then
         begin
           WNode2 := WNode.Getnext;
           WNode.Delete;
           WNode := WNode2;
         end
         else
           WNode := WNode.GetNext;
       end;
     end;

     procedure TForm1.Button1Click(Sender: TObject);
     begin
       Treeview1.Items.Clear;
       GetProcessList;
       CleanUpTree(TreeView1.Items);
     end;

     procedure TForm1.TreeView1Click(Sender: TObject);
     begin
       If Treeview1.selected.Level = 1 then //Level 1 entrys Only
       begin
         TheWinHandle := THandle(Treeview1.selected.Data); //Get the Handle from the DataOption
         // Do Something with the Handle, must not be in this Procedure
         edit1.text := IntToStr(TheWinHandle);
       end;
     end;

     procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
     begin
       TreeView1Click(Self);
     end;

     end.
---paste end

meikl ;-)
Avatar of allio

ASKER

Can I make a program that works on all OS? not just on 98 or NT
just to repost

look at www.madshi.net
there is all what you need

enumerates processes,
is win-version independent
;-)
Avatar of allio

ASKER

Can I make a program that works on all OS? not just on 98 or NT
Avatar of allio

ASKER

kretzschmar ,
  where in madshi.net can i find the answer?
  thanks
allio , I see that you aren't interested to have a full source code project for this job :(
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi guys,

thanx a lot, meikl, for (repeatedly) pointing to my homepage...  :-))

Yes, with madKernel you can do things like e.g.

  // this is the hardest close, like terminating with task manager
  Process('explorer.exe').Terminate;

  // this is a hard close, but a bit friendlier than Terminate
  Process('notepad.exe').Quit;

  // this is like clicking in [X] of the main window
  Process('calc.exe').Close;

and much more. Everything works in every OS, of course. madKernel is free for non-commercial usage, but doesn't come with sources then.

Alternatively you can use my totally free unit "enumStuff" (with sources), which can enumerate processes in every OS. You have to do the killing part yourself, in that case. But it's not difficult, just calling OpenProcess and TerminateProcess (or EnumWindows + PostMessage(WM_CLOSE)).

www.madshi.net/enumStuff.zip

Hi Nestorua, your suggestion does not work in NT4.

Hi DrDelphi, just for my interest: Does your stuff need PsApi.dll?

Hi ginsonic, which method are you using for enumerating the processes? Does it work in NT, too? Does it work for window-less processes? Do you need PsApi.dll?

Regards, Madshi.
I see that you don't wish to make public your e-mail address .

So , get this demo from my site .
http://www.ginsonic.ro/demo.zip

When click the 'List' get the list of all running applications .

When click 'Terminate' finish the selected process .

When double click an item from list then you can get all infos about that process ( ID, filename, path .... ).
Forgot to upload . Try now .
Hi ginsonic, your demo doesn't work in NT4.
I tested only in Win98 and XP
Yeah, win95, 98, ME, 2k and XP work fine, because they all support the toophelp functions. But NT4 never did and probably never will support the toophelp functions...
This question is current, others below are not and need your attention.  ADMINISTRATION WILL BE CONTACTING YOU SHORTLY.  Moderators Computer101 or Netminder will return to finalize these if they are still open in 14 days.  Experts, please post closing recommendations before that time.

Below are your open questions as of today.  Questions which have been inactive for 21 days or longer are considered to be abandoned and for those, your options are:
1. Accept a Comment As Answer (use the button next to the Expert's name).
2. Close the question if the information was not useful to you, but may help others. You must tell the participants why you wish to do this, and allow for Expert response.  This choice will include a refund to you, and will move this question to our PAQ (Previously Asked Question) database.  If you found information outside this question thread, please add it.
3. Ask Community Support to help split points between participating experts, or just comment here with details and we'll respond with the process.
4. Delete the question (if it has no potential value for others).
   --> Post comments for expert of your intention to delete and why
   --> YOU CANNOT DELETE A QUESTION with comments; special handling by a Moderator is required.

For special handling needs, please post a zero point question in the link below and include the URL (question QID/link) that it regards with details.
https://www.experts-exchange.com/jsp/qList.jsp?ta=commspt
 
Please click this link for Help Desk, Guidelines/Member Agreement and the Question/Answer process.  https://www.experts-exchange.com/jsp/cmtyHelpDesk.jsp

Click you Member Profile to view your question history and please keep them updated. If you are a KnowledgePro user, use the Power Search option to find them.  

Questions which are LOCKED with a Proposed Answer but do not help you, should be rejected with comments added.  When you grade the question less than an A, please comment as to why.  This helps all involved, as well as others who may access this item in the future.  PLEASE DO NOT AWARD POINTS TO ME.

To view your open questions, please click the following link(s) and keep them all current with updates.
https://www.experts-exchange.com/questions/Q.11410418.html
https://www.experts-exchange.com/questions/Q.20247100.html
https://www.experts-exchange.com/questions/Q.20290838.html
https://www.experts-exchange.com/questions/Q.20291273.html



*****  E X P E R T S    P L E A S E  ******  Leave your closing recommendations.
If you are interested in the cleanup effort, please click this link
https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=commspt&qid=20274643 
POINTS FOR EXPERTS awaiting comments are listed in the link below
https://www.experts-exchange.com/commspt/Q.20277028.html
 
Moderators will finalize this question if in @14 days Asker has not responded.  This will be moved to the PAQ (Previously Asked Questions) at zero points, deleted or awarded.
 
Thanks everyone.
Moondancer
Moderator @ Experts Exchange
This is a unit that I have used to do something very simillar. It is rock solid and works well.
=====================
INSTRUCTIONS FOR USE
=====================

1. Copy the ProcessViewer.pas file into a directory of your choice (recommend the directory of your project)
2. Include the Unit in your USES block.

Now you have access to the functions and properties.

Hint: The ProcessViewer only examines processes with a window handle!


Methods and functions
---------------------

METHOD GetProcessList:

      Simply call this function in your code and the ProcessViewer Unit fills the ProcessInfo array.
      You should ever use GetProcessList before you take your own action with processes.
      So you can be sure to have the newest image of the processes.

      The internal functions like kill-processes calls GetProcessList self, so you don't need this do.


FUNCTION IsFileActive(FileName: string): boolean

      This function checks, if the file "FileName" is executed.
      You can include the path and drive letter or not.
      The execution with path and drive letter is a little bit faster.
      It returns TRUE, if the file is executed and FALSE, if not.

      The function calls "GetProcessList" before it goes for checking so you don't need do this manually.

      Example:

            if IsFileActive('DELPHI32.EXE') then
            begin
                  ShowMessage('Delphi runs!');
            end;


FUNCTION KillProcessByFileName(FileName: string, KillAll: boolean): boolean

      Use this function when you want to terminate(kill) a process, when you know the name of the file.
      "FileName" is the file name of the process, that you want to kill.
      You can include the path and drive letter (i.e: c:\windows\cdplayer.exe) or not (i.e. cdplayer.exe).

      "KillAll" is a flag. When it is TRUE, ALL processes executed by the file will be terminated (a file
      can execute more than one process).
      When it is FALSE, only the first found process executed by the file will be killed.
      The order of the processes are managed by Windows, so you probably not know which process is
      exactly "your" process.

      The function returns TRUE, when it killed the process(es) successfully.
      The function returns FALSE, when the termination of all processes (KillAll=true) or one file
      (KillAll=false)      failed or the file are not executed at this time.

      The function calls "GetProcessList" before it goes for terminating so you don't need do this manually.

      Hint: On slower machines or on very busy systems it can be possible, that the return value are
      FALSE but the process is killed anyway after some milliseconds. In this case you should increase the value
      "SleepForReCheck" (see below in this file).

      Example:

            if KillProcessByFileName('CDPLAYER.EXE',true) then
            begin
                  ShowMessage('All instances of the Windows CD player are closed.');
            end;


FUNCTION KillProcessByPID(PID: DWord): boolean

      Use this function when you want to terminate(kill) a process,
      when you know the ProcessID of the process. It's seldom, but sometimes you need this function.

      It's also called internal from "KillProcessByFileName".

      "PID" is the ProcessID of the process, that you want to kill.

      The function calls "GetProcessList" before it goes for terminating so you don't need this manually.

      The function returns TRUE, when it killed the process successfully.
      The function returns FALSE, when the termination failed or the PID doesn't exist.

      Hint: On slower machines or at very busy systems it can be possible, that the return value are
      FALSE but the process is killed anyway. In this case you should increase the value
      "SleepForReCheck" (see below in this file).

      Example:

            if KillProcessByPID(3278354) then
            begin
                  ShowMessage('Process with PID '+IntToStr(3278354)+' are terminated.');
            end;




Properties
----------

This is the data structure of the ProcessInfo record:

type TProcessInfo=record
            FileName: string;
            Caption: string;
            Visible: boolean;
            Handle: DWord;
            PClass: string;
            ThreadID: DWord;
            PID: DWord;
end;

var ProcessInfo: array of TProcessInfo;

      When you call "GetProcessList" the array "ProcessInfo" will be filled with all informations
      about the running processes.

      Here are the details of the ProcessInfo structure:

      FileName:            The file that executed the process (with complete path)
      Caption:            Caption of the window (can be empty)
      Visible:             If TRUE, the window is visible
      Handle:             Internal handle of the window
      PClass:                  Internal class of the window
      ThreadID:            Internal ThreadID of the process
      PID:                        Internal ProcessID of the process (used for the kill-functions).


      Ok, this example lists all file names in a TStringList:

                  procedure ListAllFiles;
                  var
                        i: integer;
                        FileList: TStringList;
                  begin
                        FileList:=TStringList.Create;                                     //prepare the stringlist
                        GetProcessList;                                                                               //update the ProcessInfo Array
                        for i:=0 to Length(ProcessInfo)-1 do                   //walk through the ProcessInfo array
                        begin
                              FileList.Add(ProcessInfo[i].FileName);      //copy the filenames in the list
                        end;
                        .
                        .
                        .
                  end;

var
      DateiList,CaptionList,VisibleList,HandleList,ClassList,ThreadIdList,PIDList: TStringList;

      These lists are used internal by the ProcessViewer unit. They are published and can used in your code.

      So the previous example can make easier:

                  procedure ListAllFiles;
                  var
                        FileList: TStringList;
                  begin
                        FileList:=TStringList.Create;                                     //prepare the stringlist
                        GetProcessList;                                                                               //update the ProcessInfo Array
                        FileList:=DateiList;                      //copy the filelist
                        .
                        .
                        .
                  end;

            I recommend to use the ProcessInfo array and NOT the lists! When you use such created lists with
            simply a=b then a can changed when b change.

            Such programming is called "dirty code". Don't do this.

            The ProcessInfo array will be constant until you call another function of the unit.


const      SleepForReCheck;

      I use a constant "SleepForReCheck" to give the process killing functions time
      to finish the work (some processes needs more time to close all connections). The
      constant is used in a For-To-loop together with Application.ProcessMessages.

      The default value is 5000, this should be enough for the most processes. When you
      expect that your application runs on slower or busy machines then increase the value.

      Pay attention, some tools at the users controls processes (i.e. resources manager). They must recalculate
      their data between your terminate-commands. Considerate this!
      
      A good pre-check is, to open a executable more times (about 15-20 times) and try to close all with
      a KillProcessByFileName-Command. When it closes all without interrupt it is ok (on your machine).

      You can change this constant directly in the source code.




Finally
----------------
      When you don't know, what processes are and what you want with a processviewer, please don't use this unit.

      The terminating of processes is the hardest way to kick a program out of the memory. It's not the same like
      normal close with sending a WM_CLOSE message. It is like cut the powerline of a computer.

      Don't kill system processes. I'm not responsible for damages on your hardware or software!

      This Unit is freeware and I don't give support for this. Feel free to change some
      things and develope your own Unit from this.

====
Actual Unit Code

unit ProcessViewer;

interface

uses
      Windows, Dialogs, SysUtils, Classes, ShellAPI, TLHelp32, Forms;

const
      SleepForReCheck=5000;

type TProcessInfo=record
      FileName: string;
      Caption: string;
      Visible: boolean;
      Handle: DWord;
      PClass: string;
      ThreadID: DWord;
      PID: DWord;
end;


var
      DateiList,CaptionList,VisibleList,HandleList,ClassList,ThreadIdList,PIDList: TStringList;
      ProcessInfo: array of TProcessInfo;

function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): Bool; stdcall;
function KillProcessByPID(PID: DWord): boolean;
function KillProcessByFileName(FileName: string; KillAll: boolean): boolean;
procedure GetProcessList;
function GetFileNameFromHandle(Handle: hwnd):string;
function IsFileActive(FileName: String): boolean;

implementation

procedure GetProcessList;
var
      i,Laenge: integer;
begin
DateiList.Clear;
HandleList.Clear;
ClassList.Clear;
CaptionList.Clear;
VisibleList.Clear;
ThreadIdList.Clear;
PIDList.Clear;
EnumWindows(@EnumWindowsProc, 0);
Laenge:=DateiList.Count;
SetLength(ProcessInfo,Laenge);
for i:=0 to Laenge-1 do
begin
      DateiList[i]:=UpperCase(DateiList[i]);
      with ProcessInfo[i] do
      begin
            FileName:=DateiList[i];
            Caption:=CaptionList[i];
            Visible:=VisibleList[i]='1';
            Handle:=StrToInt64(HandleList[i]);
            PClass:=ClassList[i];
            ThreadID:=StrToInt64(ThreadIdList[i]);
            PID:=StrToInt64(PIDList[i]);
      end;
end;
end;

function IsFileActive(FileName: String): boolean;
var
      i: integer;
begin
result:=false;
if FileName='' then exit;
GetProcessList;
FileName:=UpperCase(ExtractFileName(FileName));
for i:=0 to Length(ProcessInfo)-1 do
begin
      if Pos(FileName,ProcessInfo[i].FileName)>0 then
      begin
            result:=true;
            break;
      end;
end;
end;

function GetFileNameFromHandle(Handle: hwnd):string;
var
      PID: DWord;
      aSnapShotHandle: THandle;
      ContinueLoop: Boolean;
      aProcessEntry32: TProcessEntry32;
begin
GetWindowThreadProcessID(Handle, @PID);
aSnapShotHandle := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
aProcessEntry32.dwSize := SizeOf(aProcessEntry32);
ContinueLoop := Process32First(aSnapShotHandle, aProcessEntry32);
while Integer(ContinueLoop) <> 0 do
begin
      if aProcessEntry32.th32ProcessID = PID then
      begin
            result:=aProcessEntry32.szExeFile;
            break;
      end;
      ContinueLoop := Process32Next(aSnapShotHandle, aProcessEntry32);
end;
CloseHandle(aSnapShotHandle);
end;

function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): Bool;
var
      Capt,Cla: array[0..255] of char;
      Datei: string;
      ident: dword;
begin
GetWindowText(hWnd, Capt, 255);
GetClassName(hwnd,Cla,255);
ThreadIdList.Add(IntToStr(GetWindowThreadProcessId(hwnd,nil)));
Datei:=GetFileNameFromhandle(hwnd);
DateiList.Add(Datei);
HandleList.Add(IntToStr(HWnd));
if IsWindowVisible(HWnd) then VisibleList.Add('1') else VisibleList.Add('0');
ClassList.Add(Cla);
CaptionList.Add(Capt);
GetWindowThreadProcessId(StrToInt(HandleList[HandleList.Count-1]),@ident);
PIDList.Add(IntToStr(ident));
Result:=true;
end;

function KillProcessByPID(PID : DWord): boolean;
var
      myhandle : THandle;
      i: integer;
begin
myhandle := OpenProcess(PROCESS_TERMINATE, False, PID);
TerminateProcess(myhandle, 0);
for i:=0 to SleepForReCheck do Application.ProcessMessages; //Genug Zeit geben
GetProcessList;
Result:=PIDList.IndexOf(IntToStr(PID))=-1;
end;

function KillProcessByFileName(FileName: string; KillAll: boolean): boolean;
var
      i: integer;
      FileFound: boolean;
begin
result:=false;
if FileName='' then exit;
FileName:=UpperCase(ExtractFileName(FileName));
result:=true;
GetProcessList;
if KillAll then
begin
      //Kill all
      FileFound:=false;
      repeat
            GetProcessList;
            FileFound:=false;
            for i:=0 to DateiList.Count-1 do
            begin
                  if Pos(Filename,DateiList[i])>0 then
                  begin
                        FileFound:=true;
                        break;
                  end;
            end;
            if i<DateiList.Count then
            begin
                  if not KillProcessByPID(StrToInt64(PIDList[i])) then
                  begin
                        result:=false;
                        exit;
                  end;
            end;
      until not FileFound;
end else
begin
      //Kill one
      for i:=0 to DateiList.Count-1 do
      begin
            if Pos(Filename,DateiList[i])>0 then break;
      end;
      if i<DateiList.Count then
      begin
            if not KillProcessByPID(StrToInt64(PIDList[i])) then
            begin
                  result:=false;
                  exit;
            end;
      end;
end;
end;

initialization
DateiList:=TStringList.Create;
HandleList:=TStringList.Create;
ClassList:=TStringList.Create;
CaptionList:=TStringList.Create;
VisibleList:=TStringList.Create;
ThreadIdList:=TStringList.Create;
PIDList:=TStringList.Create;

finalization
DateiList.Free;
HandleList.Free;
ClassList.Free;
CaptionList.Free;
VisibleList.Free;
ThreadIdList.Free;
PIDList.Free;

end.
quantum2, this code doesn't work in NT4.
at the risk of beating a dead horse, my component DOES work in NT4,Win2k and 98...


:-)
Can you be more specific than that...? I am sure it compiles and runs, did you place the kill routines in a try and except and see where it is failing...?

The code works great in XP, 2000, 2000 AS, ME, 98 and 95. I dont have an NT 4 box laying around to test on here. I can try at my other office.

Give me some more details and I will see what I can do. This is really kinda basic. Also, there have been several good posts both with code and components, certainly someone has gotten in the ball park with an answer by now.

Q2
Q2, the code you posted is built on the toolhelp functions. The toolhelp functions are available in all the OSs you listed, but they are not and will never be available in NT4. So your code can't work in NT4. There were two NT4-compatible solutions posted here already, one is DrDelphi's stuff, one is my stuff.

Regards, Madshi.
HI, Madshi,
I know about toolhelp functions and NT4.
Simply let the inquirer, allio, join two of the proposed solutions which cover all the possibilities.
Sincerely,
Nestorua.
ages ago I asked a very similar question, & as a result used processviewer.pas (thanks Dr Delphi) for a long time which worked really really well... until I ran an app on (wait for it Madshi!)...NT4..and it bombed, and it has been a bit of a nightmare...so its quite funny reading this as I really wish I'd seen it earlier.  I have to say I'm off to Madshi's site right now to get the mad suite...& do you know, I think I'm even gonna pay for it!
Best wishes P :)
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Split between geobul and kretzschmar and God_Ares

Please leave any comments here within the next seven days.
 
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
 
Paul (pnh73)
EE Cleanup Volunteer

try killtask('utilman.exe') except end;
function KillTask(ExeFileName: string): Integer;
const
PROCESS_TERMINATE = $0001;
var
ContinueLoop: BOOL;
FSnapshotHandle: THandle;
FProcessEntry32: TProcessEntry32;
begin
Result := 0;
FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);

while Integer(ContinueLoop) <> 0 do
begin
if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
UpperCase(ExeFileName))) then
Result := Integer(TerminateProcess(
OpenProcess(PROCESS_TERMINATE,
BOOL(0),
FProcessEntry32.th32ProcessID),
0));
ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);
end;

Open in new window