2008-09-03 95 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的行應該是:: WaitForSingleObject的(processInfo.hProcess,INFINITE)(沒有 '&') – wimh 2008-11-27 21:32:29

+2

爲什麼要用::對WaitForSingleObject的,但不是在其他API調用指定的全局命名空間? – 2008-11-30 13:30:49

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

在一個半相關的注意,如果你想開始有比你的當前進程更權限的進程(比如,啓動一個管理應用程序,這需要管理員權限,從運行作爲一個普通用戶的主要應用)你不能這樣做,使用在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); 
     } 
    } 
    } 
} 
3

熊,使用WaitForSingleObject可以在這種情況下讓你陷入麻煩。以下是從我的網站上的一個提示中刪除:

問題出現是因爲您的應用程序有一個窗口,但不是泵送消息。如果生成的應用程序調用其中一個廣播目標(HWND_BROADCASTHWND_TOPMOST)的SendMessage,則在所有應用程序都處理完消息之前,SendMessage將不會返回到新應用程序 - 但是您的應用程序無法處理消息因爲它是不抽的消息....所以新的應用程序鎖定,所以你的等待永遠不會成功....僵局。

如果你有過催生了應用程序的絕對控制權,那麼您可以採取的措施,如使用SendMessageTimeout,而不是SendMessage函數(例如,用於DDE灌頂,如果有人還在使用)。但有些情況會導致您無法控制的隱式SendMessage廣播,例如使用SetSysColors API。

唯一安全的方式這一輪是:

  1. 分裂出去的等待到一個單獨的線程,或
  2. 使用上等待超時和使用的PeekMessage在等待循環,以確保您抽取消息,或
  3. 使用MsgWaitForMultipleObjects API。
2

這是一個在Windows 10上工作的新例子。使用windows10 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 
相關問題