?
Solved

Terminate Running Process

Posted on 2005-03-10
18
Medium Priority
?
412 Views
Last Modified: 2010-04-05
How do I terminate a running process using delphi (same as using windows task manager - End Task). Program is not a windows program so I can't use...

var
  h: HWND;
begin
  h := FindWindow(nil, 'The Application Caption');
  if h <> 0 then PostMessage(h, WM_QUIT, 0, 0);
end;

I need to terminate using the applications name.

Thanks
Paul.
0
Comment
Question by:pr_wainwright
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
  • 2
  • +3
18 Comments
 
LVL 1

Author Comment

by:pr_wainwright
ID: 13505259
esoftbg,
           function KillTask(FileName:String):integer;

does not work on Windows NT (The process entry point Process32Next could not be located in the DLL kernel32.dll).

I don't know how to find the PID to use the following.

procedure CloseAProcess(PID: DWORD;);
var
 h: THandle;
begin
 try
   h := OpenProcess(PROCESS_TERMINATE, false, PID);
   try
     if h <> 0 then TerminateProcess(h, 0);
   finally
     CloseHandle(h);
   end;
 except
   ShowMessage('Error');
 end;
end;

The others use FindWindow & the program is not a windows program.

Regards
Paul.
 
0
 
LVL 1

Expert Comment

by:din345
ID: 13507870
you have to get the handle of the window so you can get the process id. use GetWindowThreadProcessID() to find the process id.

this works:

procedure TForm1.Button1Click(Sender: TObject);
var pid: Cardinal;
    ProcessHandle, wnd: THandle;
begin
 wnd := FindWindow(nil, 'Audacity');
 GetWindowThreadProcessID(wnd, @pid);
 ProcessHandle := OpenProcess(PROCESS_TERMINATE, FALSE, pid);
 TerminateProcess(ProcessHandle,4);
 CloseHandle(ProcessHandle);
end;
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 17

Expert Comment

by:geobul
ID: 13508390
Hi,

Here it is:

Drop a Button and Edit controls on a form. Add the code below. Write 'Project1.exe' in the Edit and press the button.

uses
 TLHelp32, PsApi;

procedure CloseAProcess(PID: DWORD);
var
 h: THandle;
begin
 try
   h := OpenProcess(PROCESS_TERMINATE, false, PID);
   try
     if h <> 0 then TerminateProcess(h, 0);
   finally
     CloseHandle(h);
   end;
 except
   ShowMessage('Error');
 end;
end;

function RunningProcessesList(List: TStrings): Boolean;

 function BuildListTH: Boolean;
 var
   SnapProcHandle: THandle;
   ProcEntry: TProcessEntry32;
   NextProc: Boolean;
 begin
   SnapProcHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   if SnapProcHandle <> THandle(-1) then
   begin
     Result := True;
     ProcEntry.dwSize := Sizeof(ProcEntry);
     NextProc := Process32First(SnapProcHandle, ProcEntry);
     while NextProc do
     begin
       List.AddObject(ProcEntry.szExeFile, Pointer(ProcEntry.th32ProcessID));
       NextProc := Process32Next(SnapProcHandle, ProcEntry);
     end;
     CloseHandle(SnapProcHandle);
   end else
     Result := False;
 end;

 function BuildListPS: Boolean;
 var
   PIDs: array[0..1024] of DWORD;
   Handle: THandle;
   Needed: DWORD;
   I: Integer;
   ModuleFileName: array[0..MAX_PATH] of Char;
 begin
   Result := EnumProcesses(@PIDs, Sizeof(PIDs), Needed);
   if not Result then Exit;
   for I := 0 to (Needed div Sizeof(DWORD)) - 1 do
     if PIDs[I] <> 0 then
     begin
       Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PIDs[I]);
       if Handle <> 0 then
       begin
         if GetModuleFileNameEx(Handle, 0, ModuleFileName, Sizeof(ModuleFileName)) = 0 then
           List.AddObject('[System]', Pointer(INVALID_HANDLE_VALUE))
         else
           List.AddObject(ModuleFileName, Pointer(PIDs[I]));
         CloseHandle(Handle);
       end;
     end;
 end;

begin
 Assert(Assigned(List));
 List.BeginUpdate;
 try
   List.Clear;
   if (Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion = 4) then
     Result := BuildListPS
   else
     Result := BuildListTH;
 finally
   List.EndUpdate;
 end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i: integer;
  PID: Cardinal;
  sl: TStringList;
begin
  sl := TStringList.Create;
  try
    RunningProcessesList(sl);
    repeat
      i := sl.IndexOf(Edit1.Text);
      if i > -1 then begin
        PID := Integer(Pointer(sl.Objects[i]));
        CloseAProcess(PID);
        sl.Delete(i);
      end;
    until i = -1;
  finally
    sl.Free;
  end;
end;

Regards, Geo
0
 
LVL 1

Author Comment

by:pr_wainwright
ID: 13514983
Geo,
      Still get this error using your code while running Windows NT4 (The process entry point Process32Next could not be located in the DLL kernel32.dll).

Any idea's

Thanks
Paul.

0
 
LVL 17

Expert Comment

by:geobul
ID: 13515737
When are you getting that error - on startup of the app or when you are pressing the button?
0
 
LVL 17

Expert Comment

by:geobul
ID: 13515820
The function BuildListTH should not be called if you're running NT4. The line:
if (Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion = 4) then
should do that.

Could you tell me what Win32Platform and Win32MajorVersion your computer reports back?

Regards, Geo
0
 
LVL 5

Expert Comment

by:Hypoviax
ID: 13522620
Try:

function KillTask(ExeFileName: string): integer; //used to kill a process
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;

This will kill a process by it's exe name e.g.

killtask('notepad.exe');

Regards,

Hypoviax
0
 
LVL 2

Expert Comment

by:StTwister
ID: 13530061
U don't need to loop through all processes to kill a specific applications if u know the window caption

var pid: Cardinal;
    Process, h: THandle;
begin
 wnd := FindWindow(nil, 'The Application Caption'); //get the window handle
 GetWindowThreadProcessID(wnd, @pid); //then get it's pid
 ProcessHandle := OpenProcess(PROCESS_TERMINATE, FALSE, pid); //open the process with termination rights using the PID
 TerminateProcess(ProcessHandle,0); // terminate the process (in this case, 0 is the exit code)
 CloseHandle(ProcessHandle); //close the process handle beacuse we don't use the process ahndle anymore
end;

This only works if you know the window caption, but not the .exe filename

StTwister
0
 
LVL 1

Author Comment

by:pr_wainwright
ID: 13533933
Geo,
       1) The error is reported at startup
       2) Windows NT 4.0 Service Pack 5 Build 1381

Regards
Paul.
0
 
LVL 17

Expert Comment

by:geobul
ID: 13590547
Sorry for the late reply. I was in another city for one week.

Can you open a new project, drop one TEdit and one TButton components on a form and apply my code above? Perhaps there is something else in your current test project which causes that error.

I cannot test it here because I have no NT4 at hand anymore but I used that code on NT 4 before (Delphi 5).

Regards, Geo
0
 
LVL 1

Author Comment

by:pr_wainwright
ID: 13600354
Geobul,
           Did not call 'BuildListTH', no error when program started but pressing the button did nothing.

Reagrds
Paul.
0
 
LVL 17

Expert Comment

by:geobul
ID: 13600825
My fault, sorry. Modify the following lines as shown below:

in BuildListTH:
   List.AddObject(UpperCase(ProcEntry.szExeFile), Pointer(ProcEntry.th32ProcessID));

in BuildListPS:
  List.AddObject(UpperCase(ExtractFileName(ModuleFileName)), Pointer(PIDs[I]));

in ButtonClick:
  i := sl.IndexOf(UpperCase(Edit1.Text));

and try again.

Regards, Geo
0
 
LVL 1

Author Comment

by:pr_wainwright
ID: 13609825
Geo,
      Get this error using your new code while running Windows NT4 (The process entry point Process32First could not be located in the DLL kernel32.dll).

Thanks
Paul.


0
 
LVL 5

Expert Comment

by:Hypoviax
ID: 13614804
Process32First and the others seem not to work in NT4. You will need to find another way to enumerate processes before you can terminate them.
0
 
LVL 17

Accepted Solution

by:
geobul earned 500 total points
ID: 13619616
Hypoviax,

that's what I'm doing in the code. If the OS is Win NT 4, I'm using psapi and BuildListPS function instead which definately worked well on that platform. The function uses EnumProcesses, OpenProcess and GetModuleFileNameWEx API functions.

I simply can't understand why BuildListTH function is being called on his computer. It shouldn't be because there is OS version check in the calling function which is correct I think.

Regards, Geo
0
 
LVL 1

Author Comment

by:pr_wainwright
ID: 13621152
Geo,
       The company where I work are rolling out XP soon & I know your initial code works ok so I will award you the points.

Thanks
Paul.
0
 
LVL 17

Expert Comment

by:geobul
ID: 13621784
Paul, thanks for the points. I'm so sorry I wasn't able to help you more.

Regards, Geo
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses
Course of the Month14 days, 3 hours left to enroll

800 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question