您也可以使用CreateProcess而不是ShellExecute/ShellExecuteEx。該函數包含一個cmd.exe包裝選項,返回退出代碼並返回stdout。 (包括可能不完美)。
注:在我的使用,我知道,必須有標準輸出的結果,但PeekedNamePipe函數並不總是返回字節數在第一次嘗試,因此循環那裏。也許,有人可以弄清楚併發布修訂?另外,也許應該生成一個替代版本,它會分別返回stderr?
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <Shellapi.h>
/*
Note:
The exitCode for a "Cmd Process" is not the exitCode
for a sub process launched from it! That can be retrieved
via the errorlevel variable in the command line like so:
set errorlevel=&[launch command]&echo.&echo exitCode=%errorlevel%&echo.
The stdOut vector will then contain the exitCode on a seperate line
*/
BOOL executeCommandLine(const CStringW &command,
DWORD &exitCode,
const BOOL asCmdProcess=FALSE,
std::vector<CStringW> *stdOutLines=NULL)
{
// Init return values
BOOL bSuccess = FALSE;
exitCode = 0;
if(stdOutLines) stdOutLines->clear();
// Optionally prepend cmd.exe to command line to execute
CStringW cmdLine((asCmdProcess ? L"cmd.exe /C " : L"") +
command);
// Create a pipe for the redirection of the STDOUT
// of a child process.
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
bSuccess = CreatePipe(&g_hChildStd_OUT_Rd,
&g_hChildStd_OUT_Wr, &saAttr, 0);
if(!bSuccess) return bSuccess;
bSuccess = SetHandleInformation(g_hChildStd_OUT_Rd,
HANDLE_FLAG_INHERIT, 0);
if(!bSuccess) return bSuccess;
// Setup the child process to use the STDOUT redirection
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Execute a synchronous child process & get exit code
bSuccess = CreateProcess(NULL,
cmdLine.GetBuffer(), // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if(!bSuccess) return bSuccess;
WaitForSingleObject(piProcInfo.hProcess, (DWORD)(-1L));
GetExitCodeProcess(piProcInfo.hProcess, &exitCode);
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
// Return if the caller is not requesting the stdout results
if(!stdOutLines) return TRUE;
// Read the data written to the pipe
DWORD bytesInPipe = 0;
while(bytesInPipe==0){
bSuccess = PeekNamedPipe(g_hChildStd_OUT_Rd, NULL, 0, NULL,
&bytesInPipe, NULL);
if(!bSuccess) return bSuccess;
}
if(bytesInPipe == 0) return TRUE;
DWORD dwRead;
CHAR *pipeContents = new CHAR[ bytesInPipe ];
bSuccess = ReadFile(g_hChildStd_OUT_Rd, pipeContents,
bytesInPipe, &dwRead, NULL);
if(!bSuccess || dwRead == 0) return FALSE;
// Split the data into lines and add them to the return vector
std::stringstream stream(pipeContents);
std::string str;
while(getline(stream, str))
stdOutLines->push_back(CStringW(str.c_str()));
return TRUE;
}
感謝。我會更深入地看。它的工作原理:) – buddy123
你一定要CloseHandle的(info.hProcess);之後? (這是在此間表示:http://www.codingnotebook.com/2012/02/wait-on-process-launched-by.html) – Robin
@Robin這是正確的,感謝 - 我已經修改了我的答案因此使它明確。 –