Как получить stdout от другого процесса в Win32 без задержки?

То, что я хотел бы сделать, подобно тому, что 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++?

6
задан Community 23 May 2017 в 11:45
поделиться