2008-09-03 33 views

Respuesta

47

Algo como esto:

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

La línea debe ser WaitForSingleObject :: WaitForSingleObject (processInfo.hProcess, infinito) (sin el '&') – wimh

+2

:: ¿Por qué utilizar para especificar el espacio de nombres global WaitForSingleObject pero no en las otras llamadas a la API? –

+2

Esa sería la fuerza del hábito –

16

Hay un ejemplo en http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx

basta con sustituir el argv[1] con su constante o variable que contiene el programa.

#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

si su exe pasa a ser una aplicación de consola, que podría estar interesado en la lectura de la stdout y stderr - por eso, voy a humildemente le remito a este ejemplo:

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

es un poco de un bocado de código, pero lo he usado variaciones de este código para generar y leer.

7

En una nota semi relacionada, si desea iniciar un proceso que tiene más privilegios que su proceso actual (por ejemplo, iniciar una aplicación administrativa, que requiere derechos de administrador, desde la aplicación principal ejecutándose como un usuario normal), no puede hacerlo utilizando CreateProcess() en Vista, ya que no activará el cuadro de diálogo UAC (suponiendo que esté habilitado). Sin embargo, el cuadro de diálogo UAC se activa cuando se usa ShellExecute().

9

Si su aplicación es una aplicación de GUI de Windows, no es ideal utilizar el código siguiente para hacer la espera, ya que los mensajes de su aplicación no recibirán procesamiento. Para el usuario, se verá como si tu aplicación se hubiera colgado.

WaitForSingleObject(&processInfo.hProcess, INFINITE) 

Algo así como el no probado código a continuación podría ser mejor ya que mantendrá el procesamiento de la cola de mensajes de Windows y la aplicación va a seguir respondiendo:

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

No, así no es cómo combina un bucle de mensaje y espera. Use MsgWaitForMultipleObjects (QS_ALLEVENTS); [http://msdn.microsoft.com/en-us/library/ms684242(VS.85).aspx] – MSalters

+2

+1 El código funcionó para mí. – mrsheen

3

Tenga en cuenta que el uso de WaitForSingleObject puede meterlo en problemas en este escenario. Lo siguiente está recortado de una sugerencia en mi sitio web:

El problema surge porque su aplicación tiene una ventana pero no está bombeando mensajes. Si la aplicación generada invoca SendMessage con uno de los destinos de difusión (HWND_BROADCAST o HWND_TOPMOST), entonces SendMessage no regresará a la nueva aplicación hasta que todas las aplicaciones hayan manejado el mensaje, pero su aplicación no puede manejar el mensaje. porque no está bombeando mensajes ... por lo que la nueva aplicación se bloquea, por lo que su espera nunca tiene éxito ... MUERTO MUERTO.

Si usted tiene el control absoluto sobre la aplicación generada, entonces hay medidas que puede tomar, como el uso SendMessageTimeout en lugar de SendMessage (por ejemplo, para las iniciaciones DDE, si alguien sigue utilizando eso).Pero hay situaciones que provocan transmisiones implícitas de SendMessage sobre las cuales no tiene control, como por ejemplo el uso de la API SetSysColors.

Las únicas formas seguras redondas esto son:

  1. partidos apagado de la espera en un hilo separado, o
  2. usar un tiempo de espera en el esperar y usar PeekMessage en su bucle de espera para asegurarse de que la bomba mensajes , o
  3. usa la API MsgWaitForMultipleObjects.
2

Aquí hay un nuevo ejemplo que funciona en Windows 10. Al usar Windows 10 SDK, debe usar CreateProcessW en su lugar. Este ejemplo está comentado y, con suerte, se explica por sí mismo.

#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 
Cuestiones relacionadas