如何在c ++中调用:: CreateProcess来启动Windows可执行文件?

寻找一个例子:

  1. 启动一个EXE
  2. 等待EXE完成。
  3. 当可执行文件完成时,正确closures所有句柄。

像这样的东西:

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

有一个例子在http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx

只需将argv[1]replace为包含程序的常量或variables即可。

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

如果您的应用程序是Windows GUI应用程序,那么使用下面的代码来执行等待并不理想,因为您的应用程序的消息不会得到处理。 对用户来说,它看起来像你的应用程序已挂起。

 WaitForSingleObject(&processInfo.hProcess, INFINITE) 

像下面未经testing的代码可能会更好,因为它将继续处理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); } } } } 

如果你的exe恰好是一个控制台应用程序,你可能有兴趣阅读stdout和stderr – 为此,我会虚心向你推荐这个例子:

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

这只是一小段代码,但是我使用了这段代码的变体来产生和读取。

在一个半相关的说明中,如果您想要启动一个比当前进程具有更多特权的进程(例如,从正常用户运行的主应用程序启动需要pipe理员权限的pipe理员应用程序),则不能在Vista上使用CreateProcess(),因为它不会触发UAC对话框(假设它已启用)。 但是,当使用ShellExecute()时触发UAC对话框。

请记住,在这种情况下使用WaitForSingleObject可能会遇到麻烦。 以下是从我的网站上的一个小贴士:

出现这个问题的原因是你的应用程序有一个窗口,但不是抽取消息。 如果生成的应用程序使用其中一个广播目标( HWND_BROADCASTHWND_TOPMOST )调用SendMessage,那么SendMessage将不会返回到新应用程序,直到所有应用程序都处理完消息 – 但是您的应用程序无法处理该消息,吨泵消息….所以新的应用程序locking,所以你的等待永远不会成功…. DEADLOCK。

如果你对生成的应用程序有绝对的控制权,那么你可以采取一些措施,比如使用SendMessageTimeout而不是SendMessage(例如,如果有人仍然在使用DDE启动)。 但是有些情况会导致您无法控制的隐式SendMessage广播,例如使用SetSysColors API。

唯一安全的方法是:

  1. 把等待分成一个单独的线程,或者
  2. 在Wait上使用超时,并在Wait循环中使用PeekMessage,以确保您输出消息或
  3. 使用MsgWaitForMultipleObjects API。

这是一个新的例子,在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