2

看起来像一个错误,不是吗?在这种情况下,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
4

2 回答 2

4

看起来像一个错误,不是吗?

不是这样的错误,而是Get-Servicecmdlet 参数设计的意外后果:

ValueFromPipeline将属性附加到类型为[string]/[string[]][object]/ [object[]](或[psobject]/ [psobject[]])的参数使该参数绑定到任何管道输入,可能除了绑定到其他参数之外 -除非该参数由命令行参数绑定,这是您的-Name *解决方法所做的。

  • 原因是任何数据类型的实例都可以转换为[string]/ 派生自[object]( [psobject]),从而导致任何输入对象(无论类型如何)都绑定到该参数。

简而言之:这里的问题不在于[pscustomobject]@{computername='comp001'} 不受约束-ComputerName——它实际上——它总是被绑定到。-Name
PowerShell参数绑定器从根本上将管道输入绑定到所有合适的参数,而不仅仅是一个。

如前所述,防止管道-Name绑定的唯一方法是通过参数传递一个值- 即使该值只是表示包含任何名称的服务。*

现在也在GitHub 上讨论这种行为。


边注:

正如js2010(OP)指出的那样,可以将and 属性有意义地组合在一个参数ValueFromPipelineValueFromPipelineByPropertyName,方式Get-Service确实如此,但请注意约束:

  • 仅适用于键入[object][psobject]/[object[]][psobject[]]的参数(这样的参数将始终按值绑定所有内容,而无需考虑属性)。

    • 如果类型是[string]or ,[string[]]考虑属性,但不能有额外的管道绑定参数,因为这会带来最初的问题:[string]/[string[]]参数也总是会绑定
  • 与参数名称匹配的输入对象的属性类型必须与参数类型匹配,或者必须至少可以转换为参数类型才能被绑定。

这是一个示例命令,它首先将相同的服务绑定-Name为字符串,然后绑定为具有.Name属性的对象:
'rpcss', [pscustomobject] @{ Name = 'rpcss' } | Get-Service

于 2018-05-15T02:30:43.817 回答
2

当您向 发送完整对象时Get-Service,它只有两个绑定选项:NameInputObject,它们是接受ByValue管道输入的参数。不幸的是,您的对象不是任何一个都可以理解的形式。

您可以通过运行以下命令查看 PowerShell 正在做什么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 ) 指出:

当参数为“真(按值)”时,Windows PowerShell 会先尝试将任何管道值与该参数相关联,然后再尝试其他方法来解释命令。

于 2018-05-13T18:42:53.240 回答