또한 ShellExecute/ShellExecuteEx 대신 CreateProcess를 사용할 수도 있습니다. 이 함수에는 cmd.exe 래퍼 옵션, 종료 코드 반환 및 stdout 반환이 포함됩니다. (포함하는 것이 완벽하지 않을 수도 있습니다).
Notes : 필자가 사용하는 것으로는 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 맞아요, 고마워요. - 그에 맞게 대답을 수정했습니다. 명백한. –