[英]PowerShell bug? Can't pipe ComputerName property to Get-Service (mixing byvalue and bypropertyname)
Seems like a bug, no?看起来像一个错误,不是吗? In this case, PowerShell converts the hashtable to a string '@{computername=comp001}' and tries to use it with -Name (ByValue) instead of -ComputerName (ByPropertyName).
在这种情况下,PowerShell 将哈希表转换为字符串 '@{computername=comp001}' 并尝试将它与 -Name (ByValue) 一起使用,而不是 -ComputerName (ByPropertyName)。 Even PS 6 does it.
甚至 PS 6 也能做到。 Piping to
Get-Service -Name *
works fine.管道到
Get-Service -Name *
工作正常。
PS C:\> [pscustomobject]@{computername='comp001'} | get-service
get-service : Cannot find any service with service name '@{computername=comp001}'.
At line:1 char:45
+ [pscustomobject]@{computername='comp001'} | get-service
+ ~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (@{computername=comp001}:String)
[Get-Service], ServiceCommandException
+ FullyQualifiedErrorId :
NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand
Seems like a bug, no?
看起来像一个错误,不是吗?
Not a bug as such, but an unexpected consequence of the parameter design of the Get-Service
cmdlet:不是错误本身,而是
Get-Service
cmdlet 参数设计的意外结果:
Attaching the ValueFromPipeline
attribute to a parameter typed [string]
/ [string[]]
or [object]
/ [object[]]
(or [psobject]
/ [psobject[]]
) makes that parameter bind to any pipeline input , possibly in addition to binding to other parameters - unless that parameter is bound by command-line argument , which is what your -Name *
workaround does.将
ValueFromPipeline
属性附加到类型为[string]
/ [string[]]
或[object]
/ [object[]]
(或[psobject]
/ [psobject[]]
)的参数会使该参数绑定到任何管道输入,可能在除了绑定到其他参数 -除非该参数由命令行参数绑定,这就是您的-Name *
解决方法所做的。
[string]
/ are derived from [object]
( [psobject]
), causing any input object, irrespective of type, to bind to that parameter.[string]
/ 派生自[object]
( [psobject]
),导致任何输入对象,无论类型如何,都绑定到该参数。 In short: the problem here isn't that [pscustomobject]@{computername='comp001'}
isn't bound to -ComputerName
- it actually is - it is that it is also bound to -Name
, invariably.简而言之:这里的问题不在于
[pscustomobject]@{computername='comp001'}
没有绑定到-ComputerName
- 它实际上是- 它也总是绑定到-Name
。
The PowerShell parameter binder fundamentally binds pipeline input to all suitable parameters , not just one. PowerShell参数绑定器从根本上将管道输入绑定到所有合适的参数,而不仅仅是一个。
As stated, the only way to prevent the -Name
binding from the pipeline is to pass a value by argument - even if that value is just *
to signal inclusion of services of any name.如上所述,防止管道中的
-Name
绑定的唯一方法是通过参数传递值 - 即使该值只是*
表示包含任何名称的服务。
The behavior is now also being discussed on GitHub .现在也在GitHub 上讨论这种行为。
Side note:边注:
As js2010 (the OP) points out, it is possible to meaningfully combine the ValueFromPipeline
and ValueFromPipelineByPropertyName
attributes in a single parameter , the way Get-Service
does, but note the constraints:作为js2010(在OP)指出,有可能有意义结合
ValueFromPipeline
和ValueFromPipelineByPropertyName
属性的一个参数,该方式Get-Service
做,但要注意的限制:
It only works for a parameter not typed [object]
or [psobject]
/ [object[]]
or [psobject[]]
(such a parameter would invariably bind everything by value without ever considering properties ).它仅适用于未键入
[object]
或[psobject]
/ [object[]]
或[psobject[]]
的参数(这样的参数将始终按值绑定所有内容,而无需考虑属性)。
[string]
or [string[]]
, properties are considered, but you cannot have additional pipeline-binding parameters , because that presents the original problem: the [string]
/ [string[]]
parameter will invariably also bind.[string]
或[string[]]
,则考虑属性,但不能有额外的管道绑定参数,因为这会带来原始问题: [string]
/ [string[]]
参数总是也会绑定. The type of an input object's property matching the parameter name must either match the parameter type or must at least be convertible to it in order to be bound.与参数名称匹配的输入对象的属性类型必须与参数类型匹配,或者必须至少可以转换为参数类型才能绑定。
Here's a sample command that binds the same service to -Name
first as a string and then as an object with a .Name
property:这是一个示例命令,它首先将相同的服务作为字符串绑定到
-Name
,然后作为具有.Name
属性的对象:
'rpcss', [pscustomobject] @{ Name = 'rpcss' } | Get-Service
As you are sending a complete object to Get-Service
, it has only two options for binding: Name
and InputObject
, which are the parameters that accept ByValue
pipeline input.当您将一个完整的对象发送到
Get-Service
,它只有两个绑定选项: Name
和InputObject
,它们是接受ByValue
管道输入的参数。 Unfortunately, your object is not in a form that either understands.不幸的是,您的对象不是可以理解的形式。
You can see what PowerShell is doing by running this Trace-Command
:您可以通过运行此
Trace-Command
来查看 PowerShell 正在做什么:
Trace-Command -Name ParameterBinding -PSHost -Expression {[pscustomobject]@{ComputerName='comp001'} | Get-Service}
As you say, the way around this is to supply a value for -Name
, so it doesn't attempt to bind it:正如您所说,解决此问题的方法是为
-Name
提供一个值,因此它不会尝试绑定它:
[pscustomobject]@{ComputerName='comp001'} | Get-Service -Name *
Once again, you can use Trace-Command
as above to see that it is now happy to bind '*' to -Name
, then it goes on to bind the additional parameters like -ComputerName
.再一次,您可以像上面一样使用
Trace-Command
来查看现在很高兴将 '*' 绑定到-Name
,然后它继续绑定其他参数,如-ComputerName
。
The PowerShell documentation ( about_Parameters ) states: PowerShell 文档 ( about_Parameters ) 指出:
When a parameter is "True (by Value)", Windows PowerShell tries to associate any piped values with that parameter before it tries other methods to interpret the command.
当参数为“True(按值)”时,Windows PowerShell 会尝试将任何管道值与该参数相关联,然后再尝试其他方法来解释命令。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.