因此,我尝试从正在生成的进程中捕获stdout
和stderr
。
1.我创建了一些FIFO:
HANDLE hstdout;
while ((hstdout = CreateNamedPipe(
stdout_filename.c_str()
, PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE
, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS
, 10
, 4096
, 4096
, 0
, &sa)) == INVALID_HANDLE_VALUE)
{
// In case the fifo is already in use, add a _ to the name and try again.
stdout_filename += L"_";
}
我对stderr
做了同样的处理。
1.然后,我创建了一个过程,包括它所需要的一切:
PROCESS_INFORMATION pi = {};
ZeroMemory(&pi, sizeof(pi));
STARTUPINFO sui = {
sizeof(STARTUPINFO) // size
, 0 // reserved
, nullptr // desktop
, nullptr // title
, 0, 0, 0, 0 // x, y, cx, cy
, 0, 0 // x buffer, y buffer
, 0 // fill attribute
, STARTF_FORCEOFFFEEDBACK // flags
| STARTF_USESTDHANDLES
, false // show window
, 0 // reserved
, 0 // reserved
, GetStdHandle(STD_INPUT_HANDLE) // stdin
, hstdout // stdout
, hstderr // stderr
};
BOOL success
= CreateProcess(
nullptr // application name
, &cmdline[0] // command line
, nullptr // process attributes
, nullptr // security attributes
, true // inherit handles
, CREATE_NO_WINDOW // creation flags
| INHERIT_PARENT_AFFINITY
, nullptr // environment
, nullptr // current directory
, &sui // startup info
, &pi // process info
);
1.然后我侍候着把手:
if (success) {
WCHAR buffer[4096];
DWORD bytesRead;
enum { eStdOut, eStdErr, eProcess };
HANDLE handles[] = { hstdout, hstderr, pi.hProcess };
DWORD waitResult;
bool process_terminated = false;
do {
waitResult = WaitForMultipleObjects(_countof(handles), handles, TRUE, INFINITE);
switch (waitResult) {
case WAIT_TIMEOUT:
log_fs << L"Error: Wait timed out\n";
break;
case WAIT_FAILED:
log_fs << L"Error: Wait failed\n";
break;
case eStdOut + WAIT_OBJECT_0:
// stdin signaled
if (ReadFile(hstdout, buffer, _countof(buffer), &bytesRead, nullptr)) {
log_fs.write(buffer, bytesRead);
wcout.write(buffer, bytesRead);
}
else {
log_fs << "Error reading from stdout" << endl << get_error() << endl;
}
break;
case eStdErr + WAIT_OBJECT_0:
// stderr signaled
if (ReadFile(hstderr, buffer, _countof(buffer), &bytesRead, nullptr)) {
log_fs.write(buffer, bytesRead);
wcerr.write(buffer, bytesRead);
}
else {
log_fs << "Error reading from stderr" << endl << get_error() << endl;
}
break;
case eProcess + WAIT_OBJECT_0:
// process signaled it terminated
log_fs << L"Process terminated" << endl;
break;
case eStdOut + WAIT_ABANDONED_0:
case eStdErr + WAIT_ABANDONED_0:
case eProcess + WAIT_ABANDONED_0:
// One of the handles have been abandoned.
log_fs << L"Error: wait abandoned " << (waitResult - WAIT_ABANDONED_0)
<< endl << get_error() << endl;
break;
default:
log_fs << L"Error: Unknown " << waitResult
<< " (" << (waitResult - WAIT_OBJECT_0)
<< ", " << (waitResult - WAIT_ABANDONED_0) << ")"
<< endl << get_error() << endl;
break;
}
} while (waitResult != WAIT_OBJECT_0 + eProcess);
if (!GetExitCodeProcess(pi.hProcess, &exitCode)) {
log_fs << L"Error getting return code\n";
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
1.然后我用我的测试程序测试它:
int main()
{
std::cout << "Hello World!\n";
std::cerr << "Hello Underworld!\n";
// std::wstring str;
// std::wcin >> str;
}
在eStdOut + WAIT_OBJECT_0
的情况下,如果没有注解,它会执行到错误else,Windows错误字符串为“Waiting for a process to open the other end of the pipe”,然后无限期地阻塞在WaitForMultipleObjects
上。
如果我取消注解测试文件中的最后两行,我的应用程序就会无限期地阻塞在WaitForMultipleObjects
上。
我做错了什么?
1条答案
按热度按时间olhwl3o21#
如果您查看MSDN上的Creating a Child Process with Redirected Input and Output示例,您将看到
CreatePipe
创建匿名管道。CloseHandle
操作!关闭stdout的写入端的技巧意味着你可以从它读取直到管道中断。当发生这种情况时,你可以对进程
WaitForSingleObject
...