我希望将 Powershell 管道行为扩展到外部应用程序。
我有一大堆 Write-Host 语句一闪而过,只有这样你才能看到输出。
Tip of the hat to marsze https://stackoverflow.com/users/2060966/marsze.
-
PowerShell [Core] v6+ performs no buffering at all, and sends (stringified) output as it is being produced by a command to an external program, in the same manner that output is streamed between PowerShell commands.[1]
-
PowerShell 的旧版(版本高达 5.1),Windows PowerShell, 缓冲区在那它收集命令的所有输出first在将其字符串化发送到外部程序之前。
-
marsze 的有用答案 https://stackoverflow.com/a/64664003/45375显示了基于直接使用 .NET API 的解决方法。
然而,我认为即使Windows PowerShell的行为不是这里的问题:你的Run-Commands
函数执行得非常快 - 考虑到它调用的函数仅输出字符串文字 - 然后将生成的行数组一次性发送到netapp.exe
- 进一步的处理,包括何时产生输出,取决于netapp.exe
. In PowerShell [核心] v6+,在 PowerShell 端缓冲的情况下,个人Run-Commmand<n>
函数的输出将被发送到netapp.exe
稍微早一点,但我不认为这会产生影响。
结果是unless netapp.exe
提供了一种调整其输入和输出缓冲的方法,您将无法控制其输入处理和输出产生的时间.
PowerShell 如何将对象发送到外部程序(本机实用程序)通过管道:
- It sends a stringified representation of each object:
- in PowerShell [核心] v6+: 当对象变得可用时.
- in Windows PowerShell:收集内存中的所有输出对象后first.
In other words: on the PowerShell side, from v6 onward, there is no buffering.[1]
可选阅读:如何使用 PowerShell字符串化管道传输到外部程序时的对象:
-
从 v7.1 开始,PowerShell 只知道text与外部程序通信时;也就是发送的数据to此类程序被转换为文本,并输出from这样的程序是解释为文本 - 尽管底层系统 IPC 功能很简单byte导管。
-
PowerShell 使用的基于 UTF-16 的 .NET 字符串根据中指定的字符编码转换为外部程序的字节流。$OutputEncoding偏好变量 https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Preference_Variables#outputencoding,遗憾的是,Windows PowerShell 中默认为 ASCII(!),现在 PowerShell [Core] v6+ 中默认为(无 BOM)UTF-8。
-
The 用于显示的表示你在 PowerShell 中看到控制台(终端)也是发送的内容to通过管道的外部程序,作为文本行,具体来说:
-
如果一个对象(已经)is a string (or [char]
实例)、PowerShell按原样将其发送到管道,但是总是附加适合平台的换行符.
-
也就是说,在 Windows 上附加 CRLF 换行符,在类 Unix 平台上附加仅 LF 换行符。
-
这种行为可能会产生问题,因为在某些情况下您会这样做not想要这样,并且没有办法阻止它 - 请参阅GitHub 问题 #5974 https://github.com/PowerShell/PowerShell/issues/5974, GitHub 问题 #13579 https://github.com/PowerShell/PowerShell/issues/13579, and 这个答案 https://stackoverflow.com/a/48372333/45375寻求解决方法。
-
If an object is, loosely speaking, a primitive type - something that is conceptually a single value, notably the various number types - it is stringified in a culture-sensitive manner, where available[3], a platform-appropriate newline is again invariably appended.
-
例如,法国文化的影响(反映在Get-Culture
), 小数1.2
- PowerShell 将其解析为[double]
值 - 发送为1,2<newline>
.
-
注意[bool]
实例是not文化敏感且始终转换为字符串True
or False
.
-
所有其他(复杂)类型均受 PowerShell 丰富的显示输出格式的约束,并且您在终端(控制台)中看到的内容也是发送到外部程序的内容 - 这不仅再次可能包含文化敏感的表示,而且通常存在问题,因为这些表示是为人类观察者设计的,而不是为程序化的加工。
The upshot:
[1] By default; however, you can explicitly request buffering - expressed as an object count - via the common -OutBuffer parameter https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_CommonParameters#outbuffer
[2] On recent macOS and Linux platforms, the stdin buffer size is 64KB
. On Unix-like platforms, utilities typically switch to line-buffering in interactive invocations, i.e. when the stream in question is connected to a terminal.
[3] The behavior is delegated to the .ToString()
method of a type at hand, i.e. whether or not that method outputs a culture-sensitive representation.