«Разбитая труба» - нормальная ошибка, когда другой конец закрывает трубу. В вашем случае это либо означает, что «другого конца» нет, либо другое приложение ничего не записало в stdout
.
Я изменил ваш код, чтобы он был скомпилированным тестовым примером - есть два случая, в которых ReadFile
завершается неудачно, не прочитав для меня никаких данных:
CreateProcess
не удалось. Я добавил assert
, чтобы эта проблема была узнаваемой. Это, конечно, приведет к поломке трубы.
- Процесс ничего не записывает в стандартный вывод. Вместо этого он может записать в свой стандартный поток ошибок. Я также перенаправил
stderr
на канал, и, как показывает мой пример echo
, теперь он получит оба потока на другом конце канала.
Код:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#define BUFSIZE 200
int main(void)
{
BOOL bSuccess;
char szCmdLine[MAX_PATH];
char chBuf[BUFSIZE];
DWORD dwRead;
HANDLE g_hChildStd_OUT_Rd2 = NULL;
HANDLE g_hChildStd_OUT_Wr2 = NULL;
SECURITY_ATTRIBUTES saAttr2;
STARTUPINFO si2;
PROCESS_INFORMATION pi2;
ZeroMemory( &si2, sizeof(si2) );
si2.cb = sizeof(si2);
ZeroMemory( &pi2, sizeof(pi2) );
//create pipe
saAttr2.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr2.bInheritHandle = TRUE;
saAttr2.lpSecurityDescriptor = NULL;
assert(CreatePipe(&g_hChildStd_OUT_Rd2, &g_hChildStd_OUT_Wr2, &saAttr2, 0));
//create child process
bSuccess = FALSE;
memset(szCmdLine, 0, MAX_PATH);
sprintf(szCmdLine, "cmd /c echo output && echo error>&2");
ZeroMemory( &pi2, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &si2, sizeof(STARTUPINFO) );
si2.cb = sizeof(STARTUPINFO);
si2.hStdOutput = g_hChildStd_OUT_Wr2;
si2.hStdError = g_hChildStd_OUT_Wr2; // also add the pipe as stderr!
si2.dwFlags |= STARTF_USESTDHANDLES;
assert(CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si2, &pi2));
//read from pipe
CloseHandle(g_hChildStd_OUT_Wr2);
memset(chBuf, 0, BUFSIZE);
for (;;)
{
bSuccess = ReadFile( g_hChildStd_OUT_Rd2, chBuf, BUFSIZE, &dwRead, NULL);
printf("%d %lu 0x%08lx\n", bSuccess, dwRead, GetLastError());
if (bSuccess)
printf("\t'%*s'\n", (int)dwRead, chBuf);
else
break;
}
return 0;
}