好像是一个bug,不是吗?在这种情况下,powershell将哈希表转换为字符串'@ {computername = comp001}',并尝试将其与-Name(ByValue)一起使用,而不是使用-ComputerName(ByPropertyName)。即便是PS 6也能做到。管道到'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
答案 0 :(得分:1)
在向Get-Service
发送完整对象时,它只有两个绑定选项:Name
和InputObject
,它们是接受ByValue
管道输入的参数。不幸的是,您的对象不是一种可以理解的形式。
通过运行此Trace-Command
:
Trace-Command -Name ParameterBinding -PSHost -Expression {[pscustomobject]@{ComputerName='comp001'} | Get-Service}
正如你所说,解决这个问题的方法是为-Name
提供一个值,所以它不会尝试绑定它:
[pscustomobject]@{ComputerName='comp001'} | Get-Service -Name *
再一次,您可以使用上面的Trace-Command
看到它现在很高兴绑定' *'到-Name
,然后继续绑定其他参数,例如-ComputerName
。
PowerShell文档(about_Parameters)声明:
当参数为" True(按值)"时,Windows PowerShell会尝试 在尝试其他之前,将任何管道值与该参数相关联 解释命令的方法。
答案 1 :(得分:1)
好像是个错误,没有?
不是这样的错误,而是Get-Service
cmdlet参数设计的意外后果:
使用{标记[string]
/ [string[]]
或[object]
/ [object[]]
(或[psobject]
/ [psobject[]]
)参数的参数{1}}属性使该参数绑定到任何管道输入,可能除了绑定到其他参数 - 除非参数由命令行参数绑定,这是你的
ValueFromPipeline
解决方法确实如此。
-Name *
/派生自[string]
([object]
),导致所有输入对象,无论类型如何,都要绑定到该参数。简而言之:此处的问题不是[psobject]
不是绑定到
[pscustomobject]@{computername='comp001'}
- 实际上是 - <{>} >
PowerShell 参数绑定器从根本上将管道输入绑定到所有合适的参数,而不只是一个。
如上所述,防止来自管道的-ComputerName
绑定的唯一方法是通过参数传递一个值 - 即使该值只是{ {1}}表示包含任何名称的服务。
现在也在讨论这种行为on GitHub。
旁注:
正如js2010(OP)指出的那样, 可能有意义地将-Name
和-Name
属性合并到单个参数 *
&#39; ValueFromPipeline
参数的方式,但请注意约束:
它仅适用于参数不类型ValueFromPipelineByPropertyName
或Get-Service
/ -Name
或[object]
(这样的参数总是会有效的在没有考虑属性的情况下,按值绑定所有。
与参数名称匹配的输入对象属性的类型必须与参数类型匹配,或者至少可以转换为它才能被绑定。
示例命令,首先将相同的服务绑定到[psobject]
作为字符串,然后绑定到具有[object[]]
属性的对象:
[psobject[]]