Как создать дочерний процесс в зависимости от его родителя? - PullRequest
8 голосов
/ 11 января 2012

Мое приложение ( main.exe ) выполняет дочерний процесс ( child.exe ), используя ShellExecuteEx.

Но когда я закрываю или убиваю (через Process-Explorer) main.exe , дочерний процесс остается активным.

Как изящно справиться с этим, когда main.exe завершается child.exe также завершается?

Ответы [ 3 ]

13 голосов
/ 11 января 2012

Вам нужно использовать заданий . Главный исполняемый файл должен создать объект задания , тогда вам нужно установить JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE флаг для вашего объекта задания.

uses
  JobsApi;
//...
var
  jLimit: TJobObjectExtendedLimitInformation;

  hJob := CreateJobObject(nil, PChar('JobName');
  if hJob <> 0 then
  begin
    jLimit.BasicLimitInformation.LimitFlags := JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
      SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, @jLimit,
        SizeOf(TJobObjectExtendedLimitInformation));
  end; 

Затем вам нужно выполнить другой процесс с функцией CreateProcess , где dwCreationFlags должно быть установлено на CREATE_BREAKAWAY_FROM_JOB. Если эта функция выполнена успешно, вызовите AssignProcessToJobObject.

function ExecuteProcess(const EXE : String; const AParams: string = ''; AJob: Boolean = True): THandle;
var
  SI : TStartupInfo;
  PI : TProcessInformation;
  AFlag: Cardinal;
begin
  Result := INVALID_HANDLE_VALUE;
  FillChar(SI,SizeOf(SI),0);
  SI.cb := SizeOf(SI);

  if AJob then
    AFlag := CREATE_BREAKAWAY_FROM_JOB
  else
    AFlag := 0;


  if CreateProcess(
     nil,
     PChar(EXE + ' ' + AParams),
     nil,
     nil,
     False,
     AFlag,
     nil,
     nil,
     SI,
     PI
     ) then
  begin
   { close thread handle }
    CloseHandle(PI.hThread);
    Result := PI.hProcess;
  end;
end;
//...
  hApp := ExecuteProcess('PathToExecutable');

  if hApp <> INVALID_HANDLE_VALUE then
  begin
     AssignProcessToJobObject(hJob, hApp);
  end;

Когда все это будет сделано, все дочерние процессы будут автоматически завершены, даже если основной исполняемый файл был уничтожен. Вы можете получить единицу JobsApi здесь . Примечание: я не проверял это с Delphi 7.

РЕДАКТИРОВАТЬ: Здесь вы можете скачать рабочий демонстрационный проект.

3 голосов
/ 11 января 2012

Попробуйте использовать Job Objects, проверьте эти функции CreateJobObject и AssignProcessToJobObject.

Объект заданияпозволяет группам процессов управляться как единое целое.Объекты заданий - это извлекаемые, защищаемые, разделяемые объекты, которые управляют атрибутами связанных с ними процессов.Операции, выполняемые над объектом задания, влияют на все процессы, связанные с объектом задания.Примеры включают принудительное ограничение, такое как размер рабочего набора и приоритет процесса, или завершение всех процессов, связанных с заданием .

0 голосов
/ 19 января 2012

Я думаю, это очень крутой код.Это работает для меня, но я добавляю некоторые изменения, чтобы пользователь мог установить флаги окна показа для дочерних процессов, таких как SW_SHOW / SW_HIDE.

...

function ExecuteProcess(const EXE : String; const AParams: string = '';
  const nCmdShow: Integer = SW_SHOW; AJob: Boolean = True): THandle;
var
  SI : TStartupInfo;
  PI : TProcessInformation;
  AFlag: Cardinal;
begin
  Result := INVALID_HANDLE_VALUE;
  FillChar(SI,SizeOf(SI),0);
  SI.cb := SizeOf(SI);
  SI.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
  SI.wShowWindow := nCmdShow;

  if AJob then
    AFlag := CREATE_BREAKAWAY_FROM_JOB
  else
    AFlag := 0;

...

...