Winapi 无法通过标准输出写入Windows管道

Winapi 无法通过标准输出写入Windows管道,winapi,visual-c++,pipe,stdio,Winapi,Visual C++,Pipe,Stdio,\u open\u osfhandle从windows文件句柄创建一个C文件描述符,\u dup可以更改现有fd的底层文件对象。当用于将stdout重定向到CreatePipepipeReadFile时,不会捕获写入stdout的输出 下面的代码片段演示了我正在尝试的核心内容。 我想创建一个匿名管道,替换stdout,以便从读取句柄读取它 我能找到的文档表明,\u open\u osfhandle和\u dup2可以执行这个诡计,而微软的文档页面专门要求尽可能在stdout中替换fd 考虑到所有

\u open\u osfhandle
从windows文件句柄创建一个C文件描述符,
\u dup
可以更改现有fd的底层文件对象。当用于将
stdout
重定向到
CreatePipe
pipe
ReadFile
时,不会捕获写入
stdout
的输出

下面的代码片段演示了我正在尝试的核心内容。 我想创建一个匿名管道,替换
stdout
,以便从读取句柄读取它

我能找到的文档表明,
\u open\u osfhandle
\u dup2
可以执行这个诡计,而微软的文档页面专门要求尽可能在stdout中替换fd

考虑到所有这些,我希望下面的代码能够立即从ReadFile返回,其中printf写入的字节与之前对
\u write
fprintf
的调用一样正常工作

HANDLE hread;
HANDLE hwrite;
SECURITY_ATTRIBUTES sa = { sizeof(sa),NULL,TRUE };
CreatePipe(&hread, &hwrite, &sa, 0);
int fd = _open_osfhandle(intptr_t(hwrite), _O_TEXT);
FILE *fp = _fdopen(fd, "w");
setvbuf(fp, NULL, _IONBF, 0);
_dup2(_fileno(fp), _fileno(stdout));
TCHAR buffer[64] = { 0 };
DWORD bytesRead;
//_write(fd, "_write", 6); // works
//fprintf(fp, "fprintf"); // works
printf("printf");
ReadFile(hread, buffer, sizeof(buffer), &bytesRead, NULL);

调查终于取得了成果。默认情况下,由_fdopen打开的文件流被缓冲,防止任何实际写入底层OS管道句柄的内容
setvbuf
可用于关闭该选项,以便立即执行写入操作

执行
dup2
重置绑定到标准输出文件描述符的底层文件会重置缓冲,因此下面的代码可以工作。对
\u fdopen
的调用在不需要时被丢弃,并且在stdout上执行“setvbuf”

HANDLE hread;
HANDLE hwrite;
SECURITY_ATTRIBUTES sa = { sizeof(sa),NULL,TRUE };
CreatePipe(&hread, &hwrite, &sa, 0);
int fd = _open_osfhandle(intptr_t(hwrite), _O_TEXT);
_dup2(fd, _fileno(stdout));
setvbuf(stdout, NULL, _IONBF, 0);
TCHAR buffer[64] = { 0 };
DWORD bytesRead;
printf("printf");
ReadFile(hread, buffer, sizeof(buffer), &bytesRead, NULL);

在什么问题上?可能的
fprintf
将数据缓存在内部缓冲区中,而不调用
WriteFile
。除非您不刷新缓冲区,否则管道中不会有数据。在Fprintft之后调用
fflush
,这就是我遇到的问题。直到我明白了
setvbuf
。最终目标是使用_dup2替换标准输出中的fd。但这仍然不起作用。