Was ich tun möchte ist ähnlich wie Visual Studio in seinem Ausgabefenster oder anderen Editoren in ihren Werkzeugfenstern: Starten Sie einen anderen Prozess B von meinem Prozess A und erfassen Sie seine Ausgabe von stdout/stderr.Wie kann man stdout von einem anderen Prozess in Win32 ohne Latenz erfassen?
Bisher habe ich es mit CreatePipe()
arbeiten, aber aus irgendeinem Grund, die Ausgabe von B kommt nicht auf B richtig, wenn es geschrieben wird. Es verhält sich eher wie ein Puffer, der gefüllt wird, und wenn er voll ist, kommt der gesamte Pufferinhalt auf einmal bei A an. Ich habe mein eigenes Testprogramm geschrieben, das etwas ausgibt und direkt danach eine fflush(stdout)
macht. Dann kommt die Ausgabe direkt bei A an. Aber ich kann den Code aller B-Prozesse, die ich auf diese Weise verwenden möchte, nicht ändern. Der Versuch, das Rohr von A zu spülen, funktioniert auch nicht.
Wie soll das funktionieren?
Meine Initialisierungscode sowie aufwändige Code:
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;
Verbrauch:
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 ...
}
}
Edit: Ich habe gerade diese Frage: Continuously read from STDOUT of external process in Ruby. Es ist das gleiche Problem, aber im Kontext von Ruby. Leider war die Lösung, eine Ruby-Bibliothek zu verwenden, die es einfach funktioniert. Wie macht die Bibliothek das? Was ist das Äquivalent in Win32/C++?
Der verknüpfte Thread ist eine * nix-Lösung. Nichts ähnliches in Win32. –
Woher wissen Sie, dass es nur mit Unix verwandt ist? Beachten Sie auch, dass es Programme auf Windows gibt, die es gut können - closed source:/ – marc40000