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

寻找一个例子:

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

Solutions Collecting From Web of "如何在c ++中调用:: CreateProcess来启动Windows可执行文件?"

像这样的东西:

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]替换为包含程序的常量或变量即可。

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

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

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

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

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

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

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

唯一安全的方法是:

  1. 把等待分成一个单独的线程,或者
  2. 在等待中使用超时,并在等待循环中使用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