Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 418
  • Last Modified:

Terminate Running Process

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
pr_wainwright
Asked:
pr_wainwright
  • 7
  • 6
  • 2
  • +3
1 Solution
 
pr_wainwrightAuthor Commented:
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
 
din345Commented:
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
geobulCommented:
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
 
pr_wainwrightAuthor Commented:
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
 
geobulCommented:
When are you getting that error - on startup of the app or when you are pressing the button?
0
 
geobulCommented:
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
 
HypoviaxCommented:
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
 
StTwisterCommented:
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
 
pr_wainwrightAuthor Commented:
Geo,
       1) The error is reported at startup
       2) Windows NT 4.0 Service Pack 5 Build 1381

Regards
Paul.
0
 
geobulCommented:
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
 
pr_wainwrightAuthor Commented:
Geobul,
           Did not call 'BuildListTH', no error when program started but pressing the button did nothing.

Reagrds
Paul.
0
 
geobulCommented:
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
 
pr_wainwrightAuthor Commented:
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
 
HypoviaxCommented:
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
 
geobulCommented:
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
 
pr_wainwrightAuthor Commented:
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
 
geobulCommented:
Paul, thanks for the points. I'm so sorry I wasn't able to help you more.

Regards, Geo
0

Featured Post

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.

  • 7
  • 6
  • 2
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now