2012-07-17 49 views
5

嗨根据this postunbuffer通过伪终端(pty)连接到一个命令,这使得系统把它视为一个交互过程,因此不使用任何stdout缓冲。什么是Windows上的非缓冲程序的等价物?

我想在Windows上使用此功能。我可以知道在Windows上相当于unbuffer程序吗?谢谢。

+0

没有等价物。 Windows没有伪终端。 – 2012-07-17 22:46:19

+0

@HarryJohnston嗨,哈利,我想用Java来执行外部命令并实时读取stdout输出。某些.exe程序因stdout缓冲而给我带来问题。程序仍在运行时,我无法获得任何stdout输出。当程序结束时,我突然得到很多标准输出。 (当我在命令提示符窗口中手动运行时,此程序能够生成实时标准输出)如果Windows中没有伪终端,我该如何解决此问题? – userpal 2012-07-18 04:04:43

+0

缓冲区不是操作系统,而是应用程序。您需要修复有问题的.exe程序,以便它们不会缓冲它们的输出。 – 2012-07-18 04:16:50

回答

2

您所描述的行为是使用运行时库进行I/O的应用程序的典型特征。默认情况下,大多数运行时库检查句柄是否是字符模式设备(如控制台),如果是,则不执行任何缓冲。 (理想情况下,运行时库会像处理控制台一样对待管道,但似乎大多数情况下不会)。

我不知道有任何明智的方法来欺骗这样的应用程序,使其思考它当它正在写入管道时正在写入控制台。

原则上,如果您知道需要多少数据,则可以使用console API functions为应用程序创建控制台以写入,然后从控制台读取输出。但是你不能从Java那里完成,你需要编写一个C应用程序来为你做。

类似地,原则上它应该可能写出一个相当于Unix伪终端的设备驱动程序,它像一个管道一样工作,但报告自己是字符模式设备。但是,编写设备驱动程序需要特定的专业知识,并且必须进行数字签名,因此除非现有产品存在,否则此方法不太可行。

+0

一个现有选项可能是[com0com](http://com0com.sourceforge.net/)null-modem模拟器。(如果我没有记错,串口通常被视为无缓冲。) – 2017-10-07 07:31:59

4

我花了一些时间在这个,并成功。我在研究期间发现了这个博客,并决定返回并提供我的解决方案,以便为下一个人节省一些时间。我以虚假电子邮件的方式回应客人,所以我不会互动,但不需要进一步的信息。

在7月18日在'12 19:41哈利·约翰斯顿写道:

“原则上,如果你知道有多少数据预期,你可以使用控制台API函数来创建一个控制台应用程序编写然后从控制台读取输出,但是你不能从Java那里完成,你需要编写一个C应用程序来为你完成。“

事情是,已经有一个实用程序来做到这一点。它的用途略有不同,但它可以用来提供理想的结果。其预期目的是使Windows控制台应用程序能够与Linux风格的tty终端进行交互。它通过运行隐藏的控制台并直接访问控制台缓冲区来完成此操作。如果你试图使用它 - 你会失败。我很幸运,发现这个实用程序有没有文档的开关,这将允许它提供简单的无缓冲输出。如果没有这些开关,它会失败并显示错误 - 输出不是tty - 尝试输出管道时。

该实用程序被称为winpty。你可以在这里得到它:

https://github.com/rprichard/winpty/releases

未公开的开关都在这里提到:

https://github.com/rprichard/winpty/issues/103

我使用MSYS2版本。你需要使用msys-2.0.dll。

只需运行:

winpty.exe -Xallow-non-tty -Xplain your_program.exe | receive_unbuffered_output.exe 

-Xallow-non-tty,将使管道输出

-Xplain,将删除添加的Linux终端转义码(或任何他们是所谓的)

所需的文件:

winpty.exe 
winpty-agent.exe 
winpty.dll 
msys-2.0.dll 

winpt y-debugserver.exe - 不需要

+0

是的,它的工作原理,帮助解决了这个问题:https://stackoverflow.com/questions/46443544/python-popen-sdtout-doesnt-get-all-的 - 输出 - 当-EXE-失败 – 2017-10-01 08:59:12

0

声明:我的回答只处理使用MSVC编译的可执行文件。

缓冲策略在Microsoft C运行时(CRT)库内编码。您可以了解详细信息here。本文建议使用控制台句柄并操纵控制台缓冲区以接收无缓冲的输出。

然而,有Microsoft C运行时内无证功能继承文件与一些内部直接使用STARTUPINFO结构的lpReserved2cbReserved2领域其父进程的标志处理。您可以在Microsoft Visual Studio提供的crt源代码中找到详细信息。或者在GitHub上搜索类似posfhnd的内容。

我们可以利用这个未公开的特性来提供一个管道句柄,并为子进程指定FOPEN | FDEV标志来欺骗子进程,将这个管道的处理方式与FILE_TYPE_CHAR句柄相同。

我有一个工作Python3 script来演示这种方法。

相关问题