写输出 -InputObject (,'Test') -NoEnumerate

Write-Output -InputObject (,'Test') -NoEnumerate

我认为这是一个仅适用于 PowerShell Windows 5.1:

的错误

当通过命名的 -InputObject 参数提供输入时,-NoEnumerate 开关不起作用:

下面的函数returns False:

Function Test {Write-Output -InputObject (,'Foo') -NoEnumerate} 
(Test) -is [Array]

虽然此函数 returns True:

Function Test {Write-Output (,'Foo') -NoEnumerate} 
(Test) -is [Array]

PowerShell Windows

Name                           Value
----                           -----
PSVersion                      5.1.17134.858
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17134.858
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

问题没有出现在 PowerShell Core
(两个函数returnTrue)

Name                           Value
----                           -----
PSVersion                      6.2.0-preview.1
PSEdition                      Core
GitCommitId                    6.2.0-preview.1
OS                             Microsoft Windows 10.0.17134
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

虽然在关于 -NoEnumeration 开关的 Write-Output cmdlet 的描述中有一个注释:

Note

This switch only works correctly with PowerShell Core 6.2 and newer. On older versions of PowerShell Core, the collection is still enumerated even with use of this switch. The behavior in PowerShell Core 6.2 is consistent with Windows PowerShell.

(如果我没看错,我明白 -NoEnumeration 开关应该只适用于 PowerShell Windows)

我已经报告了这个问题here at the Windows PowerShell [UserVoice] as guided here by the PowerShell GitHub Community,但感觉就像一个黑洞...(我以前报告过问题,但几乎没有看到任何回应)。

问题:
这确实是一个错误还是我遗漏了什么?
如果是错误,Windows PowerShell [UserVoice] 是否仍然是报告此类问题的正确地址?

的确,Windows PowerShell 中的一个 bug(直到 v5.1,最后发布的版本 -因为该错误不是安全关键的,所以它不太可能被修复) 在通过 -NoEnumerate 时仍然会导致枚举,尽管只是一个级。[1]

从(至少)v6.2.3[2]起,此错误已在 PowerShell [Core] 修复]

演示问题(下面的所有命令现在都可以在 PowerShell [Core] 中按预期工作):

WinPS> (Write-Output -NoEnumerate -InputObject 1, 2 | Measure-Object).Count
2 # !! Should be *1*, because a *single array* (with 2 elements) was passed.

注意:很容易在上面的命令中省略 Measure-Object,但这会扭曲结果:使用 ()grouping operator 围绕 [=表达式上下文中的 63=]command 导致该命令的输出被 enumerated.

有一个解决方法省略-InputObject,即将集合作为位置参数传递,令人惊讶的是,这会导致参数按原样传递(而显式使用-InputObject 枚举参数绑定时的实参:

# POSITIONAL argument binding, without -InputObject
WinPS> (Write-Output -NoEnumerate 1, 2 | Measure-Object).Count
1 # OK

请注意,此解决方法不适用于管道输入,尽管这是不寻常的情况,因为大多数命令输出集合作为一个整体到管道(他们发送他们的元素, 一个接一个):

WinPS> ( , (1, 2) | Write-Output -NoEnumerate | Measure-Object ).Count
2 # !! Should be *1*: the unwrapped outer array contains a *single [array]* element

注:外包装数组, (...),使用,的一元形式, array constructor operator) 总是 如果你想使用 表达式通过管道发送一个集合 作为一个整体 .

因此,这种单元素包装器数组技术 Write-Output -NoEnumerate 本身 的一种简洁且快速的替代方法,因此,实际上,, (1, 2) 本身 是基于管道的解决方法:它将数组操作数 (1, 2) 作为一个整体写入 到(成功)输出流。


[1] Not 使用 -NoEnumerateWindows PowerShell[=115] 中另外表现出相关错误=]: 太多枚举发生在显式使用-InputObject:

一级递归被错误应用:输入集合的元素被意外枚举以及(同样,PowerShell [Core]现在正常工作):

WinPS> (Write-Output -InputObject 1, (2, 3) | Measure-Object).Count
3 # !! This should be *2*, because the single input array has only 2 elements.
  # !! That the 2nd element is itself an array should not matter.

同样,解决方法省略 -InputObject:

# POSITIONAL argument binding, without -InputObject
WinPS> (Write-Output 1, (2, 3) | Measure-Object).Count
2 # OK

[2] 但是,从 PowerShell (Core) 7.2.2 开始,合并时仍然存在错误
-NoEnumerate 带有 标量 参数,即 位置 绑定
:

PSCore> (Write-Output -NoEnumerate 42).GetType().Name
List`1 #`# !! scalar 42 was unexpectedly wrapped in a *list*

解决方法使用-InputObject显式:

# OK, thanks to -InputObject
PSCore> (Write-Output -NoEnumerate -InputObject 42).GetType().Name
Int32 # OK

此错误 - 可能永远无法修复 - 正在 GitHub issue #5122 中进行跟踪。