2012-01-11 20 views
7

私のアプリケーション(メインファイル)は、ShellExecuteExを使用して子プロセス(child.exe)を実行しています。親プロセスに応じて子プロセスを作成する方法は?

しかし、プロセスエクスプローラを使用して閉じる(プロセスエクスプローラ経由で)メインファイルは、子プロセスがアクティブのままです。 MAIN.EXEchild.exeも終了終了したときに優雅に、それをどのように扱うか

+0

は、メインの実行ファイルが閉じるときにメインの実行ファイルは、子の実行可能ファイルにメッセージを送信するには、Get。 –

+1

メイン実行ファイルが終了したときには実行されません – ZigiZ

+1

ジョブは優雅な解決策です。また、親プロセスハンドルを継承し、終了時にシグナルが送られるのを待つこともできます。 – OnTheFly

答えて

13

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; 

次に、あなたはdwCreationFlagsCREATE_BREAKAWAY_FROM_JOBに設定する必要がありますCreateProcess機能を持つ別のプロセスを実行する必要があります。この関数が成功した場合は、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でテストしていません。

EDIT:Here作業デモプロジェクトをダウンロードできます。

+0

私はあなたのコードをテストしました。フォーム作成時に 'CreateJobObject'を使用しました。 'ExecuteProcess'のためのボタンを追加しました。子プロセスは正常に実行され、 'AssignProcessToJobObject'はTrueを返します。親アプリケーションを閉じると子プロセスは生き残ります。 – ZigiZ

+0

@ zigi70おそらくあなたは何か間違っています。私たちはマルチモジュールソフトウェアでこの技術をうまく利用しています。私は自分の答えを編集し、作業デモプロジェクトのソースコードリンクを含めました。 – Linas

+0

プロジェクト[ここ](http://www.4shared.com/zip/1yveHVAO/Jobs.html)をアップロードしました。あなたはとても親切で一見をいただけますか? – ZigiZ

3

Job Objectsを試してください。CreateJobObjectAssignProcessToJobObjectを確認してください。

ジョブオブジェクトを使用すると、プロセスのグループを1つの単位として管理できます。ジョブ オブジェクトは、それに関連付けられたプロセスの属性を制御する、命名可能で、安全で、共有可能なオブジェクトです。ジョブオブジェクトに対して実行された操作 は、ジョブオブジェクトに関連付けられたすべてのプロセスに影響します。 例には、ワーキングセットサイズやプロセス の優先度の適用、またはのジョブに関連するすべてのプロセスの終了が含まれます()。

0

非常にクールなコードだと思います。それは私のために働いていますが、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; 

...

関連する問題