我的应用程序(main.exe)正在使用ShellExecuteEx执行子进程(child.exe)。但是当我关闭或终止(通过Process-Explorer)main.exe时,子进程仍然处于活动状态。当main.exe终止child.exe也终止时,如何优雅地处理这种情况?
ShellExecuteEx
vulvrdjw1#
您需要使用jobs。主可执行文件应为create a job object,然后您需要将set 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。
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单元here。我还没在 Delphi 7上测试过。编辑:Here您可以下载工作演示项目。
eyh26e7m2#
尝试使用Job Objects,检查这些函数CreateJobObject和AssignProcessToJobObject。作业对象允许将多组进程作为一个单元进行管理。作业对象是可命名、可保护、可共享的对象,它们控制与之关联的进程的属性。在作业对象上执行的操作会影响与该作业对象关联的所有进程。示例包括强制限制(如工作集大小和进程优先级)或终止与作业关联的所有进程。
Job Objects
CreateJobObject
p4tfgftt3#
我认为,这是非常酷的代码。它对我很有效,但我添加了一些更改,使用户能够为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;
...
3条答案
按热度按时间vulvrdjw1#
您需要使用jobs。主可执行文件应为create a job object,然后您需要将set JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE标志添加到作业对象。
然后,您需要使用CreateProcess函数执行另一个进程,其中
dwCreationFlags
必须设置为CREATE_BREAKAWAY_FROM_JOB
。如果此函数成功,则调用AssignProcessToJobObject
。当所有这些都完成后,即使主可执行文件已经被终止,所有子进程也会自动终止。你可以得到JobsApi单元here。我还没在 Delphi 7上测试过。
编辑:Here您可以下载工作演示项目。
eyh26e7m2#
尝试使用
Job Objects
,检查这些函数CreateJobObject
和AssignProcessToJobObject
。作业对象允许将多组进程作为一个单元进行管理。作业对象是可命名、可保护、可共享的对象,它们控制与之关联的进程的属性。在作业对象上执行的操作会影响与该作业对象关联的所有进程。示例包括强制限制(如工作集大小和进程优先级)或终止与作业关联的所有进程。
p4tfgftt3#
我认为,这是非常酷的代码。它对我很有效,但我添加了一些更改,使用户能够为SW_SHOW/SW_HIDE等子进程设置显示窗口标志。
...
...