2008-09-03 1 views

答えて

47

このような何か:

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); 
} 
+0

のWaitForSingleObjectラインは(INFINITE processInfo.hProcess、)のWaitForSingleObject( '&' なし)::あるべき – wimh

+2

なぜ使用:: WaitForSingleObject関数ではなく、他のAPI呼び出しにグローバル名前空間を指定するために? –

+2

それは習慣の力になります –

16

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); 
} 
7

あなたのexeファイルは、コンソールアプリケーションであることを起こる場合は、あなたがstdoutとstderrを読んで興味があるかもしれない - そのために、私は謙虚にあなたを参照してくださいよこの例では:

http://support.microsoft.com/default.aspx?scid=kb;EN-US;q190351

これは、コードの一口のビットだが、私は産卵して読み取るために、このコードのバリエーションを使用しました。

7

半関連のメモで、現在のプロセスよりも多くの権限を持つプロセスを開始する場合(通常のユーザーとして実行されているメインアプリケーションから管理者権限を必要とする管理アプリケーションを起動するなど) Vista上でCreateProcess()を使用してUACダイアログを起動することはできません(有効であると仮定して)。ただし、ShellExecute()を使用すると、UACダイアログが表示されます。

9

アプリケーションが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); 
     } 
    } 
    } 
} 
+2

いいえ、それはメッセージループと待機をどのように組み合わせるかではありません。 MsgWaitForMultipleObjects(QS_ALLEVENTS)を使用します。 [http://msdn.microsoft.com/en-us/library/ms684242(VS.85).aspx] – MSalters

+2

+1コードは私のために働いた。 – mrsheen

3

ベア心​​の中でWaitForSingleObject缶を使用していることこのシナリオであなたを困らせます。以下は、私のウェブサイトのヒントから抜粋したものです。

問題は、アプリケーションにウィンドウがありますが、メッセージをポンピングしていないために発生します。スポーンされたアプリケーションがブロードキャストターゲット(HWND_BROADCASTまたはHWND_TOPMOST)のいずれかを使用してSendMessageを呼び出すと、SendMessageはすべてのアプリケーションがメッセージを処理するまで新しいアプリケーションに戻りませんが、アプリケーションはメッセージを処理できませんメッセージをポンピングしていないので....新しいアプリがロックするので、あなたの待ち時間は決して成功しません....デッドロック。あなたが生成されたアプリケーションの上に絶対的なコントロールを持っている場合は

、そのようなSendMessageTimeoutではなく、SendMessage関数を使用するなど、あなたが取ることができる措置が存在する(例えば、DDEのイニシエーションのために、誰もがまだいることを使用している場合)。しかし、たとえばSetSysColors APIを使用するなど、コントロールを持たない暗黙的なSendMessageブロードキャストを引き起こす状況があります。このラウンド

唯一の安全な方法があります。

  1. は待ちのタイムアウトを使用して、メッセージをポンプすることを確認するために、待ちループでのPeekMessageを使用して別のスレッドに待って離脱し、または
  2. 、または
  3. MsgWaitForMultipleObjects APIを使用してください。
2

これは、Windows 10で動作する新しい例です.Windows 10 SDKを使用する場合は、代わりにCreateProcessWを使用する必要があります。この例はコメントされており、うまくいけば自明です。

#ifdef _WIN32 
#include <windows.h> 
#include <stdio.h> 
#include <tchar.h> 
#include <cstdlib> 
#include <string> 
#include <algorithm> 

class process 
{ 
public: 

    static PROCESS_INFORMATION launchProcess(std::string app, std::string arg) 
    { 

     // Prepare handles. 
     STARTUPINFO si; 
     PROCESS_INFORMATION pi; // The function returns this 
     ZeroMemory(&si, sizeof(si)); 
     si.cb = sizeof(si); 
     ZeroMemory(&pi, sizeof(pi)); 

     //Prepare CreateProcess args 
     std::wstring app_w(app.length(), L' '); // Make room for characters 
     std::copy(app.begin(), app.end(), app_w.begin()); // Copy string to wstring. 

     std::wstring arg_w(arg.length(), L' '); // Make room for characters 
     std::copy(arg.begin(), arg.end(), arg_w.begin()); // Copy string to wstring. 

     std::wstring input = app_w + L" " + arg_w; 
     wchar_t* arg_concat = const_cast<wchar_t*>(input.c_str()); 
     const wchar_t* app_const = app_w.c_str(); 

     // Start the child process. 
     if(!CreateProcessW(
      app_const,  // app path 
      arg_concat,  // Command line (needs to include app path as first argument. args seperated by whitepace) 
      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()); 
      throw std::exception("Could not create child process"); 
     } 
     else 
     { 
      std::cout << "[   ] Successfully launched child process" << std::endl; 
     } 

     // Return process handle 
     return pi; 
    } 

    static bool checkIfProcessIsActive(PROCESS_INFORMATION pi) 
    { 
     // Check if handle is closed 
      if (pi.hProcess == NULL) 
      { 
       printf("Process handle is closed or invalid (%d).\n"); 
       return FALSE; 
      } 

     // If handle open, check if process is active 
     DWORD lpExitCode = 0; 
     if(GetExitCodeProcess(pi.hProcess, &lpExitCode) == 0) 
     { 
      printf("Cannot return exit code (%d).\n", GetLastError()); 
      throw std::exception("Cannot return exit code"); 
     } 
     else 
     { 
      if (lpExitCode == STILL_ACTIVE) 
      { 
       return TRUE; 
      } 
      else 
      { 
       return FALSE; 
      } 
     } 
    } 

    static bool stopProcess(PROCESS_INFORMATION &pi) 
    { 
     // Check if handle is invalid or has allready been closed 
      if (pi.hProcess == NULL) 
      { 
       printf("Process handle invalid. Possibly allready been closed (%d).\n"); 
       return 0; 
      } 

     // Terminate Process 
      if(!TerminateProcess(pi.hProcess,1)) 
      { 
       printf("ExitProcess failed (%d).\n", GetLastError()); 
       return 0; 
      } 

     // Wait until child process exits. 
      if(WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED) 
      { 
       printf("Wait for exit process failed(%d).\n", GetLastError()); 
       return 0; 
      } 

     // Close process and thread handles. 
      if(!CloseHandle(pi.hProcess)) 
      { 
       printf("Cannot close process handle(%d).\n", GetLastError()); 
       return 0; 
      } 
      else 
      { 
       pi.hProcess = NULL; 
      } 

      if(!CloseHandle(pi.hThread)) 
      { 
       printf("Cannot close thread handle (%d).\n", GetLastError()); 
       return 0; 
      } 
      else 
      { 
       pi.hProcess = NULL; 
      } 
      return 1; 
    } 
};//class process 
#endif //win32 
関連する問題