次の例を探しています。
- EXE を起動します
- EXE が終了するのを待ちます。
- 実行可能ファイルの終了時に、すべてのハンドルを適切に閉じます。
このようなもの:
STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;
if (CreateProcess(path, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
に例がありますhttp://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx
argv[1]
をプログラムを含む定数または変数に置き換えるだけです。
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain( int argc, TCHAR *argv[] )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if( argc != 2 )
{
printf("Usage: %s [cmdline]\n", argv[0]);
return;
}
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
argv[1], // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
アプリケーションが Windows GUI アプリケーションである場合、アプリケーションのメッセージが処理されないため、以下のコードを使用して待機を行うことは理想的ではありません。ユーザーには、アプリケーションがハングしたように見えます。
WaitForSingleObject(&processInfo.hProcess, INFINITE)
以下のテストされていないコードのようなものは、Windows メッセージ キューを処理し続け、アプリケーションの応答性が維持されるため、より良いかもしれません。
//-- wait for the process to finish
while (true)
{
//-- see if the task has terminated
DWORD dwExitCode = WaitForSingleObject(ProcessInfo.hProcess, 0);
if ( (dwExitCode == WAIT_FAILED )
|| (dwExitCode == WAIT_OBJECT_0 )
|| (dwExitCode == WAIT_ABANDONED) )
{
DWORD dwExitCode;
//-- get the process exit code
GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
//-- the task has ended so close the handle
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
//-- save the exit code
lExitCode = dwExitCode;
return;
}
else
{
//-- see if there are any message that need to be processed
while (PeekMessage(&message.msg, 0, 0, 0, PM_NOREMOVE))
{
if (message.msg.message == WM_QUIT)
{
return;
}
//-- process the message queue
if (GetMessage(&message.msg, 0, 0, 0))
{
//-- process the message
TranslateMessage(&pMessage->msg);
DispatchMessage(&pMessage->msg);
}
}
}
}
exeがコンソールアプリである場合は、stdoutとstderrを読むことに興味があるかもしれません。そのために、この例を謙虚に紹介します。
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q190351
少し一口のコードですが、私はこのコードのバリエーションを使用してスポーンして読み取りました。
半関連のメモとして、現在のプロセスよりも多くの権限を持つプロセスを開始したい場合 (たとえば、通常のユーザーとして実行されているメイン アプリから、管理者権限が必要な管理アプリを起動する場合)、できません。これは、Vista で CreateProcess() を使用して行います。これは、UAC ダイアログをトリガーしないためです (有効になっていると仮定します)。ただし、ShellExecute() を使用すると、UAC ダイアログがトリガーされます。
これが一番完成度が高いのではないでしょうか? http://goffconcepts.com/techarticles/createprocess.html
WaitForSingleObject
このシナリオでは、を使用すると問題が発生する可能性があることに注意してください。以下は私のウェブサイトのヒントから抜粋したものです。
この問題は、アプリケーションにウィンドウがありますが、メッセージをポンピングしていないために発生します。生成されたアプリケーションがブロードキャストターゲットの1つ(HWND_BROADCASTまたはHWND_TOPMOST)でSendMessageを呼び出す場合、SendMessageは、すべてのアプリケーションがメッセージを処理するまで新しいアプリケーションに戻りませんが、アプリはメッセージを処理できないため、メッセージを処理できません。 tメッセージをポンピングする....新しいアプリがロックされるため、待機が成功することはありません....デッドロック。
生成されたアプリケーションを完全に制御できる場合は、SendMessageではなくSendMessageTimeoutを使用するなどの対策があります(たとえば、DDEの開始の場合、誰かがまだそれを使用している場合)。ただし、たとえばSetSysColors APIを使用するなど、制御できない暗黙のSendMessageブロードキャストが発生する状況があります。
これを回避する唯一の安全な方法は次のとおりです。
MsgWaitForMultipleObjects
APIを使用します。