powershell bug?无法将computername属性传递给get-service

时间:2018-05-13 18:13:45

标签: powershell pipe pipeline parameterbinding

好像是一个bug,不是吗?在这种情况下,powershell将哈希表转换为字符串'@ {computername = comp001}',并尝试将其与-Name(ByValue)一起使用,而不是使用-Co​​mputerName(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 个答案:

答案 0 :(得分:1)

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

通过运行此Trace-Command

,您可以了解PowerShell正在做什么
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参数的方式,但请注意约束:

  • 它仅适用于参数类型ValueFromPipelineByPropertyNameGet-Service / -Name[object](这样的参数总是会有效的在没有考虑属性的情况下,按值绑定所有

  • 与参数名称匹配的输入对象属性的类型必须与参数类型匹配,或者至少可以转换为它才能被绑定。

  • 示例命令,首先将相同的服务绑定到[psobject]作为字符串,然后绑定到具有[object[]]属性的对象:
    [psobject[]]