windows 禁用重定向标准输出管道上的缓冲(Win32 API,C++)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3385427/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 14:56:47  来源:igfitidea点击:

Disable buffering on redirected stdout Pipe (Win32 API, C++)

windowswinapiredirectstdout

提问by Dave Brotherstone

I'm spawning a process from Win32 using CreateProcess, setting the hStdOutputand hStdErrorproperties of STARTUPINFOto pipe handles created with CreatePipe. I've got two threads reading the pipes, waiting for data to become available (or the process to complete, at which point it checks that there is no data left before terminating the thread).
As data becomes available, I write the output out to effectively a big textbox.

我正在从 Win32 中生成一个进程,使用CreateProcess,将hStdOutputhStdError属性设置为STARTUPINFO使用CreatePipe. 我有两个线程在读取管道,等待数据可用(或进程完成,此时它会在终止线程之前检查是否没有剩余数据)。
当数据可用时,我将输出有效地写出到一个大文本框。

What's happening is the output is being buffered, so a slow running process just gets chunks of data thrown at the text box, but not "as it happens".

发生的事情是输出被缓冲,因此运行缓慢的进程只会在文本框中获取大量数据,而不是“发生时”。

I'm not sure if it's the pipe that's doing the buffering, or something to do with the redirection.

我不确定是管道在做缓冲,还是与重定向有关。

Is there any way to either set the pipe to be unbuffered, or start the process in such a way that the stdout is sent as soon as possible?

有什么方法可以将管道设置为无缓冲,或者以尽快发送 stdout 的方式启动进程?

I'm testing with a test app that prints lines one second apart

我正在使用一个测试应用程序进行测试,该应用程序将打印行间隔一秒

Here is line one
(waits one second)
Here is line two
(waits one second)
... etc

采纳答案by Anders

The buffering is probably in the C runtime (printf etc) and there is not much you can do about it (IIRC it does a isatty() check to determine a buffering strategy)

缓冲可能在 C 运行时(printf 等)中,对此您无能为力(IIRC 它执行 isatty() 检查以确定缓冲策略)

回答by Ben Voigt

There's SetNamedPipeHandleState, but it only controls buffering for remote pipes, not when both ends are on the same computer.

SetNamedPipeHandleState,但它只控制远程管道的缓冲,而不是当两端都在同一台计算机上时。

回答by Oleg

It seems to me you can solve the problem if you set the hStdOutputand hStdErrorof STARTUPINFOnotto pipe handles created with CreatePipe, but instead of that you create a named pipes (with CallNamedPipefunction exactly like you used if before also using SECURITY_ATTRIBUTES with bInheritHandle= TRUE, see http://msdn.microsoft.com/en-us/library/aa365782.aspx) and then open there by name with respect of CreateFileusing FILE_FLAG_WRITE_THROUGHflag. Like you can read on the MSDN (http://msdn.microsoft.com/en-us/library/aa365592.aspx):

在我看来,如果您将hStdOutputand hStdErrorof STARTUPINFOnot设置为使用创建的管道句柄CreatePipe,您可以解决问题,而不是创建一个命名管道(其CallNamedPipe功能与您之前使用的功能完全相同,如果之前还使用 SECURITY_ATTRIBUTES 和bInheritHandle= TRUE,请参阅http:/ /msdn.microsoft.com/en-us/library/aa365782.aspx),然后根据CreateFile使用FILE_FLAG_WRITE_THROUGH标志的名称在那里打开。就像您可以在 MSDN ( http://msdn.microsoft.com/en-us/library/aa365592.aspx)上阅读一样:

The pipe client can use CreateFile to enable overlapped mode by specifying FILE_FLAG_OVERLAPPED or to enable write-through mode by specifying FILE_FLAG_WRITE_THROUGH.

管道客户端可以使用 CreateFile 通过指定 FILE_FLAG_OVERLAPPED 来启用重叠模式或通过指定 FILE_FLAG_WRITE_THROUGH 来启用直写模式。

So just reopen the pipe with respect of CreateFileusing FILE_FLAG_WRITE_THROUGHflag and set the handle/handles to hStdOutputand hStdErrorof STARTUPINFO.

因此,只要重新打开该管道相对于的CreateFile使用FILE_FLAG_WRITE_THROUGH标志和手柄/手柄设置为hStdOutputhStdErrorSTARTUPINFO