2008-09-03 57 views

Trả lời

47

Something như thế này:

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

Dòng WaitForSingleObject nên :: WaitForSingleObject (processInfo.hProcess, INFINITE) (không có '&') – wimh

+2

Tại sao sử dụng để xác định :: namespace toàn cục trên WaitForSingleObject nhưng không phải trên các cuộc gọi API khác? –

+2

Đó sẽ là lực lượng của thói quen –

16

Có một ví dụ tại http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx

Chỉ cần thay thế argv[1] với không đổi hoặc biến có chứa các chương trình của bạn.

#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

nếu exe của bạn sẽ xảy ra là một ứng dụng giao diện điều khiển, bạn có thể quan tâm trong việc đọc stdout và stderr - cho rằng, tôi khiêm nhường sẽ giới thiệu bạn đến ví dụ này:

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

Đó là một chút của một mouthful mã, nhưng tôi đã sử dụng các biến thể của mã này để đẻ trứng và đọc.

7

Trên ghi chú bán liên quan, nếu bạn muốn bắt đầu quy trình có nhiều đặc quyền hơn quy trình hiện tại của bạn (giả sử, khởi chạy ứng dụng quản trị, yêu cầu quyền Quản trị viên, từ ứng dụng chính đang chạy với tư cách người dùng thông thường), bạn không thể làm như vậy bằng cách sử dụng CreateProcess() trên Vista vì nó sẽ không kích hoạt hộp thoại UAC (giả sử nó được kích hoạt). Hộp thoại UAC được kích hoạt khi sử dụng ShellExecute().

9

Nếu ứng dụng của bạn là ứng dụng GUI của Windows thì việc sử dụng mã bên dưới để thực hiện việc chờ đợi không phải là lý tưởng vì tin nhắn cho ứng dụng của bạn sẽ không được xử lý. Đối với người dùng, ứng dụng của bạn sẽ bị treo.

WaitForSingleObject(&processInfo.hProcess, INFINITE) 

Cái gì như chưa được kiểm tra đang dưới đây có thể được tốt hơn vì nó sẽ giữ xử lý hàng đợi thông điệp cửa sổ và ứng dụng của bạn sẽ vẫn đáp ứng:

//-- 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

Không, đó không phải là cách bạn kết hợp vòng lặp tin nhắn và chờ đợi. Sử dụng MsgWaitForMultipleObjects (QS_ALLEVENTS); [http://msdn.microsoft.com/en-us/library/ms684242(VS.85).aspx] – MSalters

+2

+1 Mã làm việc cho tôi. – mrsheen

3

Ghi nhớ rằng việc sử dụng WaitForSingleObject thể khiến bạn gặp rắc rối trong kịch bản này. Sau đây được trích từ một mẹo trên trang web của tôi:

Sự cố xảy ra do ứng dụng của bạn có cửa sổ nhưng không bơm tin nhắn. Nếu ứng dụng sinh ra gọi SendMessage bằng một trong các mục tiêu phát sóng (HWND_BROADCAST hoặc HWND_TOPMOST), thì SendMessage sẽ không trở lại ứng dụng mới cho đến khi tất cả ứng dụng xử lý tin nhắn - nhưng ứng dụng của bạn không thể xử lý tin nhắn bởi vì nó không phải là tin nhắn bơm .... vì vậy các ứng dụng mới bị khóa, vì vậy chờ đợi của bạn không bao giờ thành công .... DEADLOCK.

Nếu bạn có quyền kiểm soát tuyệt đối đối với ứng dụng sinh sản, thì bạn có thể thực hiện các biện pháp như SendMessageTimeout thay vì SendMessage (ví dụ:Nhưng có những tình huống gây ra các chương trình phát sóng SendMessage tiềm ẩn mà bạn không có quyền kiểm soát, chẳng hạn như sử dụng API SetSysColors chẳng hạn.

duy nhất cách an toàn vòng này là:

  1. tách ra các Chờ thành một chủ đề riêng biệt, hoặc
  2. sử dụng một thời gian chờ trên Chờ và sử dụng PeekMessage trong vòng lặp Chờ của bạn để đảm bảo rằng bạn bơm thông điệp hoặc
  3. sử dụng API MsgWaitForMultipleObjects.
2

Đây là ví dụ mới hoạt động trên cửa sổ 10. Khi sử dụng SDK windows10, bạn phải sử dụng CreateProcessW thay thế. Ví dụ này được bình luận và hy vọng tự giải thích.

#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 
Các vấn đề liên quan