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
pipeReadFile
时,不会捕获写入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。但这仍然不起作用。