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 !!!!!
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 !!!!!
yes, multiple possibilities
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
procedure TForm1.Button2Click(Sender
var
H : HWND;
begin
H := FindWindow('notepad', nil);
if IsWindow(H) then
PostMessage(H, WM_CLOSE, 0, 0);
end;
Regards, Geo
ASKER
what if it does not have a window? but the exe is still running in the windows processes? how can you kill it?
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);
for MSWord: H := FindWindow('OpusApp', nil);
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
how do you get the PID?
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?
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(h wnd, @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(GetWindo wLong(hwnd ,GWL_HINST ANCE),wn,s izeof(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(@EnumWindowsPr oc,0);
ListBox1.Items.AddStrings( S);
finally
S.Free;
end;
end;
end.
now implement geobul's code.
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
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(h
// 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(GetWindo
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(@EnumWindowsPr
ListBox1.Items.AddStrings(
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?
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!!
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
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
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
look at www.madshi.net
there is all what you need
enumerates processes,
is win-version independent
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
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
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
Regards,
Nick
Ginsonic,
You can get that from my site... see above.
Good luck!!
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.
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 .
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.AddC hild(WNode ,StrPas(@W Name[0]));
WNode2.Data := Ptr(H); {Store the Handle in the DataOption}
end;
Result := True;
end;
Procedure TForm1.GetThreads(ProcessI D : DWord);
var
ThreadEntry32 : TThreadEntry32; {Defined in TlHelp32}
TLHandle : THandle;
begin
TLHandle := CreateToolhelp32Snapshot(T H32CS_SNAP THREAD, 0);
if Thread32First(TLHandle,Thr eadEntry32 ) then
begin
if ThreadEntry32.th32OwnerPro cessID = ProcessID then
EnumThreadWindows(ThreadEn try32.th32 ThreadID,@ TWCallBack ,0);
while Thread32Next(TLHandle,Thre adEntry32) do
if ThreadEntry32.th32OwnerPro cessID = ProcessID then
EnumThreadWindows(ThreadEn try32.th32 ThreadID,@ TWCallBack ,0);
end;
CloseHandle(TLHandle);
end;
Procedure TForm1.GetProcesslist;
var
PLHandle : Thandle;
ProcessEntry32 : TProcessEntry32; {Defined in TlHelp32}
begin
PLHandle := CreateToolhelp32Snapshot(T H32CS_SNAP PROCESS, 0);
if Process32First(PLHandle,Pr ocessEntry 32) then
begin
Wnode := TreeView1.Items.Add(Nil,st rPas(@Proc essEntry32 .szExeFile [0]));
GetThreads(ProcessEntry32. th32Proces sID);
while Process32Next(PLHandle,Pro cessEntry3 2) do
begin
Wnode := TreeView1.Items.Add(Nil,st rPas(@Proc essEntry32 .szExeFile [0]));
GetThreads(ProcessEntry32. th32Proces sID);
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.Item s);
end;
procedure TForm1.TreeView1Click(Send er: 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(Sen der: TObject; Node: TTreeNode);
begin
TreeView1Click(Self);
end;
end.
---paste end
meikl ;-)
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],
WNode2 := Form1.TreeView1.Items.AddC
WNode2.Data := Ptr(H); {Store the Handle in the DataOption}
end;
Result := True;
end;
Procedure TForm1.GetThreads(ProcessI
var
ThreadEntry32 : TThreadEntry32; {Defined in TlHelp32}
TLHandle : THandle;
begin
TLHandle := CreateToolhelp32Snapshot(T
if Thread32First(TLHandle,Thr
begin
if ThreadEntry32.th32OwnerPro
EnumThreadWindows(ThreadEn
while Thread32Next(TLHandle,Thre
if ThreadEntry32.th32OwnerPro
EnumThreadWindows(ThreadEn
end;
CloseHandle(TLHandle);
end;
Procedure TForm1.GetProcesslist;
var
PLHandle : Thandle;
ProcessEntry32 : TProcessEntry32; {Defined in TlHelp32}
begin
PLHandle := CreateToolhelp32Snapshot(T
if Process32First(PLHandle,Pr
begin
Wnode := TreeView1.Items.Add(Nil,st
GetThreads(ProcessEntry32.
while Process32Next(PLHandle,Pro
begin
Wnode := TreeView1.Items.Add(Nil,st
GetThreads(ProcessEntry32.
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
begin
Treeview1.Items.Clear;
GetProcessList;
CleanUpTree(TreeView1.Item
end;
procedure TForm1.TreeView1Click(Send
begin
If Treeview1.selected.Level = 1 then //Level 1 entrys Only
begin
TheWinHandle := THandle(Treeview1.selected
// Do Something with the Handle, must not be in this Procedure
edit1.text := IntToStr(TheWinHandle);
end;
end;
procedure TForm1.TreeView1Change(Sen
begin
TreeView1Click(Self);
end;
end.
---paste end
meikl ;-)
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
;-)
look at www.madshi.net
there is all what you need
enumerates processes,
is win-version independent
;-)
ASKER
Can I make a program that works on all OS? not just on 98 or NT
ASKER
kretzschmar ,
where in madshi.net can i find the answer?
thanks
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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').Te rminate;
// this is a hard close, but a bit friendlier than Terminate
Process('notepad.exe').Qui t;
// 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.
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').Te
// this is a hard close, but a bit friendlier than Terminate
Process('notepad.exe').Qui
// 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 .... ).
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
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(File Name: 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('CDP LAYER.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.Crea te; //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,Visi bleList,Ha ndleList,C lassList,T hreadIdLis t,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.Crea te; //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.ProcessMessage s.
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-Comm and. 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,Visi bleList,Ha ndleList,C lassList,T hreadIdLis t,PIDList: TStringList;
ProcessInfo: array of TProcessInfo;
function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): Bool; stdcall;
function KillProcessByPID(PID: DWord): boolean;
function KillProcessByFileName(File Name: string; KillAll: boolean): boolean;
procedure GetProcessList;
function GetFileNameFromHandle(Hand le: 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(@EnumWindowsPr oc, 0);
Laenge:=DateiList.Count;
SetLength(ProcessInfo,Laen ge);
for i:=0 to Laenge-1 do
begin
DateiList[i]:=UpperCase(Da teiList[i] );
with ProcessInfo[i] do
begin
FileName:=DateiList[i];
Caption:=CaptionList[i];
Visible:=VisibleList[i]='1 ';
Handle:=StrToInt64(HandleL ist[i]);
PClass:=ClassList[i];
ThreadID:=StrToInt64(Threa dIdList[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(Extrac tFileName( 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(Hand le: hwnd):string;
var
PID: DWord;
aSnapShotHandle: THandle;
ContinueLoop: Boolean;
aProcessEntry32: TProcessEntry32;
begin
GetWindowThreadProcessID(H andle, @PID);
aSnapShotHandle := CreateToolHelp32SnapShot(T H32CS_SNAP PROCESS, 0);
aProcessEntry32.dwSize := SizeOf(aProcessEntry32);
ContinueLoop := Process32First(aSnapShotHa ndle, aProcessEntry32);
while Integer(ContinueLoop) <> 0 do
begin
if aProcessEntry32.th32Proces sID = PID then
begin
result:=aProcessEntry32.sz ExeFile;
break;
end;
ContinueLoop := Process32Next(aSnapShotHan dle, aProcessEntry32);
end;
CloseHandle(aSnapShotHandl e);
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( GetWindowT hreadProce ssId(hwnd, nil)));
Datei:=GetFileNameFromhand le(hwnd);
DateiList.Add(Datei);
HandleList.Add(IntToStr(HW nd));
if IsWindowVisible(HWnd) then VisibleList.Add('1') else VisibleList.Add('0');
ClassList.Add(Cla);
CaptionList.Add(Capt);
GetWindowThreadProcessId(S trToInt(Ha ndleList[H andleList. Count-1]), @ident);
PIDList.Add(IntToStr(ident ));
Result:=true;
end;
function KillProcessByPID(PID : DWord): boolean;
var
myhandle : THandle;
i: integer;
begin
myhandle := OpenProcess(PROCESS_TERMIN ATE, False, PID);
TerminateProcess(myhandle, 0);
for i:=0 to SleepForReCheck do Application.ProcessMessage s; //Genug Zeit geben
GetProcessList;
Result:=PIDList.IndexOf(In tToStr(PID ))=-1;
end;
function KillProcessByFileName(File Name: string; KillAll: boolean): boolean;
var
i: integer;
FileFound: boolean;
begin
result:=false;
if FileName='' then exit;
FileName:=UpperCase(Extrac tFileName( 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(StrToInt6 4(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(StrToInt6 4(PIDList[ i])) then
begin
result:=false;
exit;
end;
end;
end;
end;
initialization
DateiList:=TStringList.Cre ate;
HandleList:=TStringList.Cr eate;
ClassList:=TStringList.Cre ate;
CaptionList:=TStringList.C reate;
VisibleList:=TStringList.C reate;
ThreadIdList:=TStringList. Create;
PIDList:=TStringList.Creat e;
finalization
DateiList.Free;
HandleList.Free;
ClassList.Free;
CaptionList.Free;
VisibleList.Free;
ThreadIdList.Free;
PIDList.Free;
end.
=====================
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
begin
ShowMessage('Delphi runs!');
end;
FUNCTION KillProcessByFileName(File
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('CDP
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.Crea
GetProcessList; //update the ProcessInfo Array
for i:=0 to Length(ProcessInfo)-1 do //walk through the ProcessInfo array
begin
FileList.Add(ProcessInfo[i
end;
.
.
.
end;
var
DateiList,CaptionList,Visi
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.Crea
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.ProcessMessage
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-Comm
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,Visi
ProcessInfo: array of TProcessInfo;
function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): Bool; stdcall;
function KillProcessByPID(PID: DWord): boolean;
function KillProcessByFileName(File
procedure GetProcessList;
function GetFileNameFromHandle(Hand
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(@EnumWindowsPr
Laenge:=DateiList.Count;
SetLength(ProcessInfo,Laen
for i:=0 to Laenge-1 do
begin
DateiList[i]:=UpperCase(Da
with ProcessInfo[i] do
begin
FileName:=DateiList[i];
Caption:=CaptionList[i];
Visible:=VisibleList[i]='1
Handle:=StrToInt64(HandleL
PClass:=ClassList[i];
ThreadID:=StrToInt64(Threa
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(Extrac
for i:=0 to Length(ProcessInfo)-1 do
begin
if Pos(FileName,ProcessInfo[i
begin
result:=true;
break;
end;
end;
end;
function GetFileNameFromHandle(Hand
var
PID: DWord;
aSnapShotHandle: THandle;
ContinueLoop: Boolean;
aProcessEntry32: TProcessEntry32;
begin
GetWindowThreadProcessID(H
aSnapShotHandle := CreateToolHelp32SnapShot(T
aProcessEntry32.dwSize := SizeOf(aProcessEntry32);
ContinueLoop := Process32First(aSnapShotHa
while Integer(ContinueLoop) <> 0 do
begin
if aProcessEntry32.th32Proces
begin
result:=aProcessEntry32.sz
break;
end;
ContinueLoop := Process32Next(aSnapShotHan
end;
CloseHandle(aSnapShotHandl
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(
Datei:=GetFileNameFromhand
DateiList.Add(Datei);
HandleList.Add(IntToStr(HW
if IsWindowVisible(HWnd) then VisibleList.Add('1') else VisibleList.Add('0');
ClassList.Add(Cla);
CaptionList.Add(Capt);
GetWindowThreadProcessId(S
PIDList.Add(IntToStr(ident
Result:=true;
end;
function KillProcessByPID(PID : DWord): boolean;
var
myhandle : THandle;
i: integer;
begin
myhandle := OpenProcess(PROCESS_TERMIN
TerminateProcess(myhandle,
for i:=0 to SleepForReCheck do Application.ProcessMessage
GetProcessList;
Result:=PIDList.IndexOf(In
end;
function KillProcessByFileName(File
var
i: integer;
FileFound: boolean;
begin
result:=false;
if FileName='' then exit;
FileName:=UpperCase(Extrac
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])
begin
FileFound:=true;
break;
end;
end;
if i<DateiList.Count then
begin
if not KillProcessByPID(StrToInt6
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])
end;
if i<DateiList.Count then
begin
if not KillProcessByPID(StrToInt6
begin
result:=false;
exit;
end;
end;
end;
end;
initialization
DateiList:=TStringList.Cre
HandleList:=TStringList.Cr
ClassList:=TStringList.Cre
CaptionList:=TStringList.C
VisibleList:=TStringList.C
ThreadIdList:=TStringList.
PIDList:=TStringList.Creat
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
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.
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.
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 :)
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
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;