Home > database >  How to kill a process started by .BAT file, which was started by CreateProcess?
How to kill a process started by .BAT file, which was started by CreateProcess?

Time:07-20

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 process ping terminates.

  • But with:

    sParams := 'run.bat';
    

    and its content of

    ping 127.0.0.1 -t
    

    calling TerminateProcess(FProcessHandle, 0) succeeds, too, but the process ping 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;
  • Related