tl; dr:
根本问题影响着双方Windows PowerShell and PowerShell(核心)7+,至少到 v7.3.4(截至撰写本文时为当前版本),并且由于它是设计行为的(不幸的)副作用,因此可能会也可能不会得到修复。
防止出现输出出故障了, force 同步显示输出, by 明确地呼叫Format-Table https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/format-table or Out-Host https://learn.microsoft.com/powershell/module/microsoft.powershell.core/out-host:
getUsersAndGroups | Format-Table
getRunningProcesses | Format-Table
Both Format-Table
and Out-Host
修复是什么主要是一个display problem,但他们是次优的解决方案因为他们俩干扰提供输出as data:
相关的GitHub 问题:
背景资料:
InsidePowerShell 会话:
-
This is 主要是一个display problem, 你也是not需要此解决方法来捕获变量中的输出,将其重定向到文件,或通过管道传递它。
-
You do需要它交互的依赖显示输出的脚本show按输出顺序,其中特别包括确保打印相关信息在出现交互式提示之前; e.g.:
# !! Without Format-table, the prompt shows *first*.
[pscustomobject] @{ foo = 1; bar = 2 } | Format-Table
Read-Host 'Does the above look OK?'
从外部,当调用PowerShell时CLI https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe (powershell -file ...
or powershell -command ...
):
-
如果出现以下情况,则可能会发生实际数据丢失:Out-Host
is not used,因为如果脚本/命令以以下结尾,挂起的异步输出可能永远不会打印exit
- see GitHub 问题 #13985 https://github.com/PowerShell/PowerShell/issues/13985; e.g.:
# !! Prints only 'first'
powershell.exe -command "'first'; [pscustomobject] @{ foo = 'bar' }; exit"
-
However, unlike in intra-PowerShell-session use, Format-Table
or Out-Host
fix both the display and the data-capturing / redirection problem, because even Out-Host
's output is sent to stdout, as seen by an outside caller (but note that the for-display representations that PowerShell's output-formatting system produces aren't generally suitable for programmatic processing).[1]
注:以上所有内容同样适用于PowerShell(核心)7+和它的pwsh https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pwshCLI,至少达到 v7.3.1。
本例中 PowerShell 有问题的行为的解释:
用以下方法演示问题可能会有所帮助MCVE(最小、完整且可验证的示例) https://stackoverflow.com/help/mcve:
Write-Host "-- before"
[pscustomobject] @{ one = 1; two = 2; three = 3 }
Write-Host "-- after"
在 PSv5+ 中,这会产生:
-- before
-- after
one two three
--- --- -----
1 2 3
发生了什么?
这个有用的答案 https://stackoverflow.com/a/34858911/45375解释为什么会发生这种情况;简而言之:
-
Implicit输出根据输出对象的类型进行格式化;就目前的情况而言,Format-Table
被隐式使用。
-
In Psv5+, 隐含地应用Format-Table
now waits长达 300 毫秒。以确定合适的列宽.
-
但请注意,这仅适用于其类型的输出对象表格格式说明 https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_format.ps1xml are 未预定义;如果他们是,they提前确定列宽,无需等待。
-
测试给定类型是否具有全名<FullTypeName>
有与之关联的表格式数据,您可以使用以下命令:
# Outputs $true, if <FullTypeName> has predefined table-formatting data.
Get-FormatData <FullTypeName> -PowerShellVersion $PSVersionTable.PSVersion |
Where-Object {
$_.FormatViewDefinition.Control.ForEach('GetType') -contains [System.Management.Automation.TableControl]
}
-
不幸的是,这意味着后续命令在该时间窗口内执行,可能会产生不相关的输出(通过管道)通过传递输出命令如Write-Host
) 或提示用户输入before Format-Table
输出开始。
- 当调用 PowerShell CLI 时从外部 and
exit
在时间窗口内调用,所有待处理的输出 - 包括后续的同步输出 - 有效丢弃的.
有问题的行为在中讨论GitHub 问题 #4594 https://github.com/PowerShell/PowerShell/issues/4594;虽然仍有希望找到解决方案,但很长时间没有任何进展。
注意:这个答案最初错误地“归咎于”PSv5+ 300 毫秒。潜在令人惊讶的标准输出格式化行为的延迟(即first发送到管道的对象决定了显示格式all管道中的对象,如果应用表格式 - 请参阅这个答案 https://stackoverflow.com/a/45705068/45375).
[1] The CLI allows you to request output in a structured text format, namely the XML-based serialization format known as CLIXML, with -OutputFormat Xml
. PowerShell uses this format behind the scenes for serializing data across processes, and it is not usually known to outside programs, which is why -OutputFormat Xml
is rarely used in practice. Note that when you do use it, the Format-Table
/ Out-Host
workarounds would again not be effective, given that the original output objects are lost.