То, что я хотел бы сделать, подобно тому, что Visual Studio делает в ее окне вывода или других редакторах в их окнах инструментов: Запустите другой процесс B с моего процесса A и получите его вывод stdout/stderr.
До сих пор я получил его работающий с CreatePipe()
, но по некоторым причинам, вывод B не прибывает в право B, когда это записано. Это ведет себя больше как буфер некоторого вида, заполняется и когда это полно, все буферное содержание прибывает в сразу. Я записал свою собственную тестовую программу, которая производит что-то и делает fflush(stdout)
непосредственно впоследствии. Затем вывод непосредственно прибывает в A. Но я не могу изменить код всех процессов B, я хотел бы использовать тот путь. Попытка сбросить канал от также не работает.
Как это, как предполагается, работает?
Мой код инициализации, а также использующий код:
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
err = CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &sa, stdouthistory);
if (err == 0)
return 1;
err = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup , 0,
FALSE,
DUPLICATE_SAME_ACCESS);
if (err == 0)
return 3;
CloseHandle(hChildStdoutRd);
DWORD a, b, c;
a = PIPE_READMODE_BYTE | PIPE_NOWAIT;
b = 0;
c = 0;
SetNamedPipeHandleState(hChildStdoutRdDup, &a, &b, &c);
err = CreatePipe(&hChildStdinRd, &hChildStdinWr, &sa, stdinhistory);
if (err == 0)
return 1;
err = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup , 0,
FALSE,
DUPLICATE_SAME_ACCESS);
if (err == 0)
return 4;
CloseHandle(hChildStdinWr);
a = PIPE_READMODE_BYTE | PIPE_NOWAIT;
b = 0;
c = 0;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.wShowWindow = SW_SHOW;
si.hStdOutput = hChildStdoutWr;
si.hStdError = hChildStdoutWr;
si.hStdInput = hChildStdinRd;
ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );
err = CreateProcess(0, this->cmdline, 0, 0, true, CREATE_NO_WINDOW, 0, 0, &si, &pi);
if (err == 0)
return 4;
Потребление:
DWORD avail;
unsigned int ofs = 0;
if (PeekNamedPipe(hChildStdoutRdDup, NULL, 0, NULL, &avail, NULL))
{
if (avail != 0)
{
int err = ReadFile(hChildStdoutRdDup, s + ofs, slen, &threadbuffern, 0);
// Consume ...
}
}
Править: Я просто нашел этот вопрос: Непрерывно читайте из STDOUT внешнего процесса в Ruby. Это - та же проблема, но в контексте Ruby. Печально решение состояло в том, чтобы пользоваться некоторой библиотекой Ruby, которая просто заставляет его работать. Как та библиотека делает это? Каков эквивалент в Win32/C++?