The clean kill option with TerminateProcess:
As mentioned above, this is not a very good option, but maybe you don’t need more, so I’ll give an example.
program KillTest; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.SyncObjs, WinApi.Windows; procedure DoWork(); begin Writeln('Worker'); while True do begin Sleep(500); end; end; procedure CreateWaitKillWorker(const ExeName: String); var Si: TStartupInfo; Pi: TProcessInformation; CommandLine: String; begin Writeln('Manager'); CommandLine := ExeName + ' -C'; Si := Default(TStartupInfo); Si.cb := sizeof(si); if CreateProcess(nil, PChar(CommandLine), nil, nil, false, CREATE_NEW_CONSOLE, nil, nil, Si, Pi) then begin try Sleep(5000); TerminateProcess(Pi.hProcess, 0); finally CloseHandle(Pi.hProcess); CloseHandle(Pi.hThread); end; end; Readln; end; var ChildProcExeName: String; begin try ChildProcExeName := ParamStr(0); if ParamCount > 0 then DoWork() else CreateWaitKillWorker(ChildProcExeName); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
TEvent polite kill option:
This option is better if you need to close the child process more accurately.
program KillTest; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.SyncObjs, WinApi.Windows; procedure DoWork(); var Event: TEvent; begin Writeln('Worker'); Event := TEvent.Create(nil, True, False, 'Test'); try while Event.WaitFor(0) = TWaitResult.wrTimeout do begin Sleep(2000); end; finally Event.Free; end; end; procedure CreateWaitKillWorker(const ExeName: String); var Si: TStartupInfo; Pi: TProcessInformation; CommandLine: String; Event: TEvent; begin Writeln('Manager'); CommandLine := ExeName + ' -C'; Si := Default(TStartupInfo); Si.cb := sizeof(si); Event := TEvent.Create(nil, True, False, 'Test'); try if CreateProcess(nil, PChar(CommandLine), nil, nil, false, CREATE_NEW_CONSOLE, nil, nil, Si, Pi) then begin try Sleep(5000); Event.SetEvent(); //WaitForSingleObject(Pi.hProcess, INFINITE); // если не обходимо ждать finally CloseHandle(Pi.hProcess); CloseHandle(Pi.hThread); end; end; finally Event.Free; end; Readln; end; var ChildProcExeName: String; begin try ChildProcExeName := ParamStr(0); if ParamCount > 0 then DoWork() else CreateWaitKillWorker(ChildProcExeName); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
PS: Examples in the console, but nothing prevents them from being used in the window application, although for windows I would prefer the option that described kot-da-vinci