2008-09-03 11 views
32

एक उदाहरण है कि के लिए खोज रहे:मैं Windows निष्पादन योग्य लॉन्च करने के लिए C++ में CreateProcess को कैसे कॉल करूं?

  1. की शुरूआत एक EXE EXE के लिए
  2. वेट्स खत्म करने के लिए।
  3. निष्पादन योग्य समाप्त होने पर सभी हैंडल को उचित रूप से बंद कर देता है।

उत्तर

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, अनंत) (बिना 'और') – wimh

+2

का प्रयोग क्यों :: WaitForSingleObject पर लेकिन अन्य API कॉल पर नहीं वैश्विक नामस्थान निर्दिष्ट करने के लिए? –

+2

यह आदत का बल होगा –

16

बस अपने निरंतर या कार्यक्रम युक्त चर के साथ argv[1] की जगह http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx

पर एक उदाहरण है।

#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

अर्ध-संबंधित नोट पर, यदि आप ऐसी प्रक्रिया शुरू करना चाहते हैं जिसमें आपकी वर्तमान प्रक्रिया से अधिक विशेषाधिकार हैं (कहें, एक व्यवस्थापक ऐप लॉन्च करना, जिसके लिए सामान्य उपयोगकर्ता के रूप में चल रहे मुख्य ऐप से व्यवस्थापक अधिकारों की आवश्यकता होती है) आप विस्टा पर CreateProcess() का उपयोग करके ऐसा नहीं कर सकते क्योंकि यह यूएसी संवाद को ट्रिगर नहीं करेगा (माना जाता है कि यह सक्षम है)। हालांकि, ShellExecute() का उपयोग करते समय यूएसी संवाद ट्रिगर किया जाता है।

9

यदि आप एक विंडोज जीयूआई एप्लीकेशन है तो इंतजार करने के लिए नीचे दिए गए कोड का उपयोग आदर्श नहीं है क्योंकि आपके आवेदन के लिए संदेश प्रसंस्करण नहीं हो रहे हैं। उपयोगकर्ता को ऐसा लगेगा कि आपका आवेदन लटका हुआ है।

WaitForSingleObject(&processInfo.hProcess, INFINITE) 

कुछ अपरीक्षित कोड की तरह नीचे बेहतर रूप में यह विंडोज़ संदेश कतार प्रसंस्करण रखेंगे हो सकता है और आपके आवेदन उत्तरदायी रहेगा: मन में

//-- 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 का उपयोग कर सकते हैं इस परिदृश्य में आपको परेशानी में डाल दें। निम्नलिखित मेरी वेबसाइट पर एक टिप से फिसल गया है:

समस्या उत्पन्न होती है क्योंकि आपके एप्लिकेशन में एक विंडो है लेकिन संदेश पंप नहीं कर रही है। यदि स्पॉन्डेड एप्लिकेशन प्रसारण लक्ष्यों में से एक के साथ SendMessage को आमंत्रित करता है (HWND_BROADCAST या HWND_TOPMOST), तो SendMessage नए एप्लिकेशन पर वापस नहीं आ जाएगा जब तक कि सभी एप्लिकेशन ने संदेश को संभाला नहीं है - लेकिन आपका ऐप संदेश को संभाल नहीं सकता क्योंकि यह संदेश पंप नहीं कर रहा है .... इसलिए नया ऐप लॉक हो गया है, इसलिए आपका इंतजार कभी सफल नहीं होता .... डेडलॉक। (उदाहरण के लिए डीडीई पहल के लिए, किसी को अभी भी उस का उपयोग कर रहा है, तो)

आप पैदा की आवेदन पर पूर्ण नियंत्रण है, तो इस तरह के SendMessageTimeout बजाय SendMessage का उपयोग कर के रूप में उपायों ले जा सकते हैं, कर रहे हैं।लेकिन ऐसी स्थितियां हैं जो अंतर्निहित SendMessage प्रसारण का कारण बनती हैं जिन पर आपके पास कोई नियंत्रण नहीं है, उदाहरण के लिए SetSysColors API का उपयोग करना।

केवल सुरक्षित तरीके इस दौर कर रहे हैं:

  1. विभाजित एक अलग थ्रेड में रुको, या
  2. प्रतीक्षा पर एक टाइमआउट उपयोग करें और अपनी प्रतीक्षा पाश में PeekMessage का उपयोग सुनिश्चित करें कि आप संदेशों पंप , या
  3. MsgWaitForMultipleObjects API का उपयोग करें।
2

यहां एक नया उदाहरण है जो विंडोज़ 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 
संबंधित मुद्दे

 संबंधित मुद्दे