For example:
var
sParams: string;
SI: TStartupInfo;
PI: TProcessInformation;
begin
FillChar(SI, SizeOf(SI), #0);
FillChar(PI, SizeOf(PI), #0);
with SI do
begin
cb := SizeOf(SI);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := SW_SHOW
end;
sParams := 'ping 127.0.0.1 -t';
UniqueString(sParams);
if CreateProcess(nil, PChar(sParams), nil, nil, False, 0, nil, nil, SI, PI) then
FProcessHandle := PI.hProcess;
If I call
TerminateProcess(FProcessHandle, 0)
the console closes successfully and the processping
terminates.But with:
sParams := 'run.bat';
and its content of
ping 127.0.0.1 -t
calling
TerminateProcess(FProcessHandle, 0)
succeeds, too, but the processping
continues to run. How to kill that process, which was started by the BAT file?
CodePudding user response:
TerminateProcess
just kills a single process. When you run that .bat the process tree will look like this:
you.exe
|
\ cmd.exe /c run.bat
|
\ ping.exe 127.0.0.1 -t
To kill a child process and its children you need to use a job object. Start your child process suspended, add it to a job and then resume its thread.
CodePudding user response:
Use the following function by passing PI.dwProcessId
from your code as the PID parameter.
function KillProcessTree(const PID: Cardinal): boolean;
var hProc, hSnap,
hChildProc : THandle;
pe : TProcessEntry32;
bCont : BOOL;
begin
Result := true;
FillChar(pe, SizeOf(pe), #0);
pe.dwSize := SizeOf(pe);
hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap <> INVALID_HANDLE_VALUE) then
begin
if (Process32First(hSnap, pe)) then
begin
hProc := OpenProcess(PROCESS_ALL_ACCESS, false, PID);
if (hProc <> 0) then
begin
Result := Result and TerminateProcess(hProc, 1);
WaitForSingleObject(hProc, INFINITE);
CloseHandle(hProc);
end;
bCont := true;
while bCont do
begin
if (pe.th32ParentProcessID = PID) then
begin
KillProcessTree(pe.th32ProcessID);
hChildProc := OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
if (hChildProc <> 0) then
begin
Result := Result and TerminateProcess(hChildProc, 1);
WaitForSingleObject(hChildProc, INFINITE);
CloseHandle(hChildProc);
end;
end;
bCont := Process32Next(hSnap, pe);
end;
end;
CloseHandle(hSnap);
end;
end;