简体   繁体   English

Powershell 参数绑定 ByPropertyName 和 ByValue

[英]Powershell Parameter binding ByPropertyName and ByValue

I want to stop a service named "ALG" so I use: "alg" | stop-service我想停止一个名为“ALG”的服务,所以我使用: "alg" | stop-service "alg" | stop-service It works. "alg" | stop-service工作原理。 Get-help stop-service -parameter name says: Pipeline input:true(ByPropertyName, ByValue) and "alg" is "ByPropertyValue" right? Get-help stop-service -parameter name说:管道输入:true(ByPropertyName,ByValue)和“alg”是“ByPropertyValue”对吗? I want to stop a process named notepad so I use: "notepad" | stop-process我想停止一个名为记事本的进程,所以我使用: "notepad" | stop-process "notepad" | stop-process and I get an error. "notepad" | stop-process ,我得到一个错误。 Get-help stop-process -parameter name says: Pipeline input true(ByPropertyName) and "notepad" is "ByPropertyName"? Get-help stop-process -parameter name说:Pipeline input true(ByPropertyName) and "notepad" is "ByPropertyName"? Why this error?为什么会出现这个错误? Thanks for your help谢谢你的帮助

If you want to bind an object's value to a parameter by property name , either:如果要通过属性名称将对象的值绑定到参数,则:

  1. Pass an object with an appropriately named property:传递具有适当命名属性的 object:
[pscustomobject]@{Name='notepad'} |Stop-Process
# or, for older versions of powershell:
'notepad' |Select @{Name='Name';Expression={$_}} |Stop-Process
  1. Explicitly bind a pipeline expression to the named parameter:将管道表达式显式绑定到命名参数:
'notepad' |Stop-Process -Name {$_}
  • Mathias R.马蒂亚斯 R。 Jessen's answer provides a solution for piping strings (process names) to Stop-Process . Jessen 的回答提供了一种将字符串(进程名称)传递到Stop-Process解决方案

  • js2010's answer has the correct explanation for why piping strings to Stop-Process doesn't work (without extra effort), and also offers a helpful technique for tracing parameter binding, but - as of this writing - the answer contains incidental information that confuses the issue a bit. js2010 的答案正确解释为什么管道字符串到Stop-Process不起作用(无需额外的努力),并且还提供了一种有用的技术来跟踪参数绑定,但是 - 在撰写本文时 - 答案包含混淆的附带信息问题有点。

Let me offer a more detailed explanation:让我提供一个更详细的解释:


Stop-Process , unlike Stop-Service , is not designed to accept strings (process names) as pipeline input. Stop-ProcessStop-Service不同,它的设计目的不是接受字符串(进程名称)作为管道输入。

While string input in the abstract can still work, namely if the strings can automatically be converted to one of the data types expected by a command's ByValue (whole-object) pipeline-binding parameters, this is not the case with Stop-Process , because a process name (string) cannot (automatically) be converted to a System.Diagnostics.Process instance ( -InputObject ) [1] .虽然抽象中的字符串输入仍然可以工作,即如果字符串可以自动转换为命令的ByValue (整个对象)管道绑定参数所期望的数据类型之一,则Stop-Process不是这种情况,因为进程名称(字符串)不能(自动)转换为System.Diagnostics.Process实例( -InputObject[1]

  • When PowerShell considers binding pipeline input to parameter -Name during a call, it looks for an object with a Name property , because the parameter declaration specifies that pipeline input is accepted only if the input object has a property named for the parameter :当 PowerShell 考虑在调用期间将管道输入绑定到参数-Name时,它会查找具有Name属性的 object ,因为参数声明指定当输入 object具有以下属性时才接受管道输入:

    • In help topics, such as the one for Stop-Process , this is expressed as ByPropertyName .在帮助主题中,例如Stop-Process的帮助主题中,这表示为ByPropertyName

    • In code, it is expressed as the Boolean ValueFromPipelineByPropertyName property of the System.Management.Automation.ParameterAttribute type;在代码中表示为System.Management.Automation.ParameterAttribute类型的 Boolean ValueFromPipelineByPropertyName属性; that is, expressed in PowerShell code, the parameter declaration looks something like: Note that ValueFromPipelineByPropertyName is short for ValueFromPipelineByPropertyName = $true也就是说,用 PowerShell 代码表示,参数声明类似于:注意ValueFromPipelineByPropertyNameValueFromPipelineByPropertyName = $true的缩写
      [Parameter(ValueFromPipelineByPropertyName)] [string[]] $Name

  • A [string] (System.String ) instance such as "alg" doesn't have a Name property - it is itself the name.诸如"alg"类的[string] (System.String ) 实例没有Name属性 - 它本身就是名称。

  • Therefore, in the absence of an automatic conversion [1] to the System.Diagnostics.Process type of the only ByValue parameter, -InputObject , and in the absence of Name and Id properties for the ByPropertyValue parameters, invocation fails with the following error message, which in essence tells you that the pipeline input is invalid (cannot be bound to any parameters):因此,如果没有自动转换[1]到唯一ByValue参数-InputObjectSystem.Diagnostics.Process类型,并且没有ByPropertyValue参数的NameId属性,调用将失败并显示以下错误消息,它本质上告诉你管道输入是无效的(不能绑定到任何参数):

    • The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

Stop-Service , by contrast, is designed to accept string input , because its -Name parameter is (also) declared as accepting strings directly as input objects, as a whole .相比之下, Stop-Service设计为接受字符串输入,因为它的-Name参数(也)被声明为作为一个整体直接接受字符串作为输入对象。

  • In help topics, such as the one for Stop-Service , this is expressed as ByValue .在帮助主题中,例如Stop-Service的帮助主题中,这表示为ByValue

  • In PowerShell code, it is expressed as ValueFromPipeline :在 PowerShell 代码中,它表示为ValueFromPipeline
    [Parameter(ValueFromPipeline)] [string[]] $Name

Note:笔记:

  • While a given parameter can be both ByValue and ByPropertyValue - which is indeed the case for Stop-Service 's -Name parameter - that isn't typical.虽然给定的参数可以ByValueByPropertyValue - 这确实是Stop-Service-Name参数的情况 - 这并不典型。

  • Often, pipeline-binding parameters are declared as scalars rather than arrays (eg, for Sort-Object , -InputObject <PSObject> rather than -InputObject <PSObject[]> ), which means that passing multiple arguments is only supported via the pipeline, not by direct argument - see this GitHub issue for background information.通常,管道绑定参数被声明为标量而不是 arrays(例如,对于Sort-Object-InputObject <PSObject>而不是-InputObject <PSObject[]> ),这意味着仅支持通过管道传递多个 arguments,不是通过直接论证 - 有关背景信息,请参阅此 GitHub 问题


Examining pipeline-binding parameters:检查管道绑定参数:

  • A command's given parameter :命令的给定参数
PS> Get-Help Stop-Process -Parameter Name

-Name <String[]>
    Specifies the process names of the processes to stop. You can type multiple process names, separated by commas, or use wildcard characters.

    Required?                    true
    Position?                    named
    Default value                None
    Accept pipeline input?       True (ByPropertyName)
    Accept wildcard characters?  true

Note the Accept pipeline input?注意Accept pipeline input? line;线; for a non -pipeline-binding parameter, you'd see False in the second column.对于管道绑定参数,您会在第二列中看到False

  • All pipeline-binding parameters supported by a given command:给定命令支持的所有管道绑定参数
PS> (Get-Help Stop-Process -Parameter *).Where({ $_.pipelineInput -like 'True*' })

-Id <Int32[]>
    Specifies the process IDs of the processes to stop. To specify multiple IDs, use commas to separate the IDs. To find the PID of a process, type 
    `Get-Process`.

    Required?                    true
    Position?                    0
    Default value                None
    Accept pipeline input?       True (ByPropertyName)
    Accept wildcard characters?  false


-InputObject <Process[]>
    Specifies the process objects to stop. Enter a variable that contains the objects, or type a command or expression that gets the objects.

    Required?                    true
    Position?                    0
    Default value                None
    Accept pipeline input?       True (ByValue)
    Accept wildcard characters?  false


-Name <String[]>
    Specifies the process names of the processes to stop. You can type multiple process names, separated by commas, or use wildcard characters.

    Required?                    true
    Position?                    named
    Default value                None
    Accept pipeline input?       True (ByPropertyName)
    Accept wildcard characters?  false

[1] Unless a parameter is declared to support a custom type conversion via a System.Management.Automation.ArgumentTransformationAttribute -derived attribute (which is uncommon), PowerShell's usual conversion rules apply here, which employ several techniques, discussed in this answer . [1] 除非通过System.Management.Automation.ArgumentTransformationAttribute派生属性(不常见)声明参数支持自定义类型转换,否则此处适用 PowerShell 的常用转换规则,该规则采用了本答案中讨论的多种技术。 In the case of System.Diagnostics.Process , conversion from a string isn't possible, because the target type neither has a single-argument constructor that has a string, nor does it have a static .Parse() method.System.Diagnostics.Process的情况下,无法从字符串进行转换,因为目标类型既没有具有字符串的单参数构造函数,也没有 static .Parse()方法。 A quick test for convertibility is to attempt a cast : [System.Diagnostics.Process] 'notepad' fails.可转换性的快速测试是尝试强制转换[System.Diagnostics.Process] 'notepad'失败。 By contrast, [System.ServiceProcess.ServiceController] 'alg' works, because that type does have a single-parameter constructor that accepts a string , but note that this conversion does not come into play during parameter binding in a call to Stop-Service such as 'alg' | Stop-Service相比之下, [System.ServiceProcess.ServiceController] 'alg'有效,因为该类型确实具有接受 string 的单参数构造函数,但请注意,此转换不会在调用Stop-Service参数绑定期间发挥作用例如'alg' | Stop-Service 'alg' | Stop-Service - there, the string is bound as-is to the ByValue -Name parameter. 'alg' | Stop-Service - 在那里,字符串按原样绑定到ByValue -Name参数。

"stop-service -name" can be piped byvalue (string), so it uses that. “stop-service -name”可以按值(字符串)传递,所以它使用它。 Stop-process fails to convert a string to the process type for -inputobject, which is pipe byvalue.停止进程无法将字符串转换为 -inputobject 的进程类型,即 pipe 按值。 "Stop-process -name" is bypropertyname only. “停止进程名称”仅由属性名称提供。

There's a little more nuance going on here.这里还有一些细微差别。 A string can be coerced to type servicecontroller, but not to type process.可以强制字符串键入 servicecontroller,但不能强制键入 process。 So a string could theoretically be piped in as -inputobject for stop-service, but not for stop-process.因此,理论上可以将字符串作为 -inputobject 用于停止服务,但不能用于停止过程。 "stop-service -inputobject alg" works as well, but "stop-process -inputobject notepad" does not. “stop-service -inputobject alg”也可以,但“stop-process -inputobject notepad”不能。 The inconsistency between these two commands can be confusing.这两个命令之间的不一致可能会令人困惑。

[System.ServiceProcess.ServiceController]'alg'

Status   Name               DisplayName
------   ----               -----------
Stopped  alg                Application Layer Gateway Service


[system.diagnostics.process]'notepad'
InvalidArgument: Cannot convert the "notepad" value of type "System.String" to type "System.Diagnostics.Process".

If you really want to see the bindings:如果您真的想查看绑定:

trace-command parameterbinding {'alg' | stop-service} -pshost
trace-command parameterbinding {'notepad' | stop-process} -pshost

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM