我认为这是一个仅适用于PowerShell Windows 5.1的错误:
通过命名的-NoEnumerate
参数提供输入时,-InputObject
开关不起作用:
以下函数返回False
:
Function Test {Write-Output -InputObject (,'Foo') -NoEnumerate}
(Test) -is [Array]
此函数返回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 中。
(两个函数都返回True
)
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
尽管在Write-Output
cmdlet的有关-NoEnumeration
开关的说明中有一个注释:
注意
此开关仅适用于PowerShell Core 6.2和更高版本。 在旧版的PowerShell Core上,集合仍 即使使用此开关也可以枚举。 PowerShell中的行为 Core 6.2与Windows PowerShell一致。
(如果我没看错,我知道-NoEnumeration
开关应该只适用于PowerShell Windows)
我已经在here的指导下Windows PowerShell [UserVoice]在here报告了PowerShell GitHub Community问题,但感觉就像是一个黑洞……(我已经报告了问题之前,但几乎看不到任何回应。
问题:
这确实是一个错误还是我错过了什么?
如果是错误,Windows PowerShell [UserVoice]仍然是报告此类问题的正确地址吗?
答案 0 :(得分:1)
确实是 Windows PowerShell 中的一个错误(直到v5.1,最后一个要发布的版本-由于该错误不是安全性至关重要的漏洞,因此< em>不太可能是固定的)。通过-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
是很诱人的,但这会扭曲结果:使用()
,在{em>命令周围使用grouping operator 在表达式的上下文中会导致该命令的输出被枚举。
有一个解决方法: 省略 -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)是<如果要通过管道使用 expression 将集合作为整体发送 ,则必须始终使用em> 。
因此,这种单元素包装器数组技术是Write-Output -NoEnumerate
本身的一种简洁快捷的替代方法,因此,实际上是 , (1, 2)
本身就是基于管道的解决方法:它将数组操作数(1, 2
)作为一个整体写入(成功)输出流。
[1] 不使用-NoEnumerate
还会在 Windows PowerShell 中显示一个相关的错误:太多枚举发生明确使用-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.0.0-rc.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
正在this GitHub issue中跟踪该错误。