[英]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:如果要通过属性名称将对象的值绑定到参数,则:
[pscustomobject]@{Name='notepad'} |Stop-Process
# or, for older versions of powershell:
'notepad' |Select @{Name='Name';Expression={$_}} |Stop-Process
'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-Process
与Stop-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 代码表示,参数声明类似于:注意
ValueFromPipelineByPropertyName
是ValueFromPipelineByPropertyName = $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
参数-InputObject
的System.Diagnostics.Process
类型,并且没有ByPropertyValue
参数的Name
和Id
属性,调用将失败并显示以下错误消息,它本质上告诉你管道输入是无效的(不能绑定到任何参数):
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.虽然给定的参数可以是
ByValue
和ByPropertyValue
- 这确实是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 问题。
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
。
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.