看起来像个bug,不是吗?在这种情况下,PowerShell将哈希表转换为字符串“@{computername= comp 001}”,并尝试将其与-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
2条答案
按热度按时间iyfjxgzm1#
看起来像只虫子,不是吗?
不是这样的错误,而是
Get-Service
cmdlet的参数设计的意外结果:ValueFromPipeline
属性附加到[string]
/[string[]]
或[object]
/[object[]]
类型的参数(或[psobject]
/[psobject[]]
)使该参数绑定到 * 任何 * 管道输入**,可能 * 除了 * 绑定到其他参数之外-* 除非 * 该参数由 * 命令行参数 * 绑定,这正是您的-Name *
工作区所做的。[string]
/是从[object]
([psobject]
)派生的,这导致 * any * 输入对象(无论类型如何)绑定到该参数。简而言之:这里的问题不是
[pscustomobject]@{computername='comp001'}
* 没有 * 绑定到-ComputerName
-它实际上 * 是 *-而是它 * 也 * 绑定到-Name
,这是不变的。PowerShell参数绑定器从根本上将管道输入绑定到 * 所有 * 合适的参数,而不仅仅是一个。
如前所述,防止
-Name
绑定进入 * 管道 * 的唯一方法是通过 * 参数 * 传递一个值--即使该值只是*
,以表示包含任何名称的服务。现在也在讨论on GitHub的行为。
旁注:
正如js2010(OP)所指出的,它 * 有 * 可能 * 在一个 * 参数中有意义地组合
ValueFromPipeline
和ValueFromPipelineByPropertyName
属性,就像Get-Service
所做的那样,但是注意约束:[object]
或[psobject]
/[object[]]
或[psobject[]]
的参数(这样的参数总是 * 按值 * 绑定所有内容,而从不考虑 * 属性 *)。[string]
或[string[]]
,则会 * 考虑属性,但不能有 * 附加的 * 管道绑定参数**,因为这会带来原始问题:[string]
/[string[]]
参数将总是 * 也 * 绑定。下面是一个示例命令,它首先将同一服务作为字符串绑定到
-Name
,然后作为具有.Name
属性的对象绑定到-Name
:x1米30英寸1x
qni6mghb2#
当您将一个完整的对象发送到
Get-Service
时,它只有两个绑定选项:Name
和InputObject
,它们是接受ByValue
管道输入的参数。不幸的是,您的对象不是这两个参数都能理解的形式。您可以通过运行以下
Trace-Command
来查看PowerShell正在执行的操作:正如您所说,解决方法是为
-Name
提供一个值,这样它就不会试图绑定它:[pscustomobject]@{ComputerName='comp001'} | Get-Service -Name *
再一次,您可以像上面那样使用
Trace-Command
,看到它现在很乐意将'*'绑定到-Name
,然后它继续绑定其他参数,如-ComputerName
。PowerShell文档(about_Parameters)指出:
当参数为“True(按值)"时,Windows PowerShell会先尝试将任何管道值与该参数关联,然后再尝试其他方法解释命令。