Điều tôi muốn làm tương tự với những gì Visual Studio thực hiện trong cửa sổ đầu ra của nó hoặc các trình soạn thảo khác trong cửa sổ công cụ của họ: Bắt đầu một quy trình B khác từ quy trình A của tôi và bắt đầu ra stdout/stderr của nó.Cách lấy stdout từ một tiến trình khác trong Win32 mà không có độ trễ?
Cho đến nay, tôi đã làm việc với CreatePipe()
, nhưng vì một lý do nào đó, đầu ra của B không đến B ngay khi được viết. Nó hoạt động giống như một bộ đệm của một số loại được lấp đầy và khi nó đầy, tất cả các nội dung bộ đệm đến A cùng một lúc. Tôi đã viết chương trình thử nghiệm của riêng mình để xuất kết quả và thực hiện trực tiếp fflush(stdout)
sau đó. Sau đó, đầu ra trực tiếp đến A. Nhưng tôi không thể thay đổi mã của tất cả các quy trình B tôi muốn sử dụng theo cách đó. Cố gắng tuôn ra ống từ A cũng không hoạt động.
Làm cách nào để hoạt động?
mã khởi tạo của tôi cũng như đang tiêu thụ:
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;
tiêu thụ:
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: Tôi chỉ tìm thấy câu hỏi này: Continuously read from STDOUT of external process in Ruby. Đó là cùng một vấn đề, nhưng trong bối cảnh của Ruby. Đáng buồn là giải pháp là sử dụng một số thư viện Ruby mà chỉ làm cho nó hoạt động. Thư viện đó làm như thế nào? Tương đương trong Win32/C++ là gì?
Chuỗi được liên kết là giải pháp * nix. Không có gì tương tự trong Win32. –
Làm thế nào để bạn biết rằng nó chỉ liên quan đến unix? Cũng lưu ý rằng có tồn tại các chương trình trên các cửa sổ có thể thực hiện tốt các mã nguồn đóng:/ – marc40000