如何解决无法使用 PowerShell 传输控制台应用程序的无限输出
在开发控制台应用程序期间,我注意到我无法在 PowerShell 中将其输出通过管道传输到自身中。
我创建了一个小型复制品(来源如下),其工作方式如下:
PS> .\but-why.exe print # continuously prints a random number every 500 ms
1746112985
1700785785
331650882
...
PS> .\but-why.exe read # echoes stdin
foo # this was typed
read 'foo'
bar # this too
read 'bar'
PS> "foo","bar" | .\but-why.exe read
read 'foo'
read 'bar'
但是当我尝试将 print
的输出输入 read
时什么也没有发生:
PS> .\but-why.exe print | .\but-why.exe read
当我将所有输出重定向到成功流时相同:
PS> .\but-why.exe print *>&1 | .\but-why.exe read
但是,当我使用 CMD 时,一切都按预期工作:
CMD> but-why.exe print | but-why.exe read
read '317394436'
read '1828759797'
read '767777814'
...
通过调试,我发现第二个实例 .\but-why.exe read
似乎从未启动过。
也许是我比较老的 PS 版本?
PS> $host.Version
Major Minor Build Revision
----- ----- ----- --------
5 1 19041 610
控制台应用程序的来源(net5.0):
using System;
using System.Threading;
switch (args[0]) {
case "print": Print(); break;
case "read": Read(); break;
}
void Print() {
var rng = new Random();
while (true) {
Console.WriteLine(rng.Next());
Thread.Sleep(500);
}
}
void Read() {
string? text;
while ((text = Console.ReadLine()) != null) {
Console.WriteLine($"read '{text}'");
}
}
解决方法
您在 Windows PowerShell 中看到了设计限制,此限制已在跨平台 PowerShell [Core] 7+ 版本中得到修复:
当 Windows PowerShell 将数据传送到外部程序(然后总是文本)时,它意外地不表现出通常的流式传输行为。
也就是说,Windows PowerShell 不会在生成它们时将其传递给它们,而是尝试首先将它们全部收集到内存中,在将它们通过管道传输到外部程序之前。
在您的情况下,因为第一个程序永远不会停止产生输出,Windows PowerShell 引擎永远不会停止等待所有输出被收集,因此有效地挂起(直到它最终耗尽内存) - 目标程序甚至从未启动,因为那只会在收集输出完成后发生。
解决方法:
-
如果可行,请切换到 PowerShell [Core] 7+,这里的限制已被移除。
-
在 Windows PowerShell 中,通过
cmd.exe
调用您的管道,正如您所观察到的那样,它确实表现出预期的流式传输行为。# Workaround via cmd.exe cmd /c '.\but-why.exe print | .\but-why.exe read'
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。