我想停止一个名为“ALG”的服务,所以我使用:
"alg" | stop-service
它有效。Get-help stop-service -parameter name
说:管道输入:true(ByPropertyName,ByValue)和“alg”是“ByPropertyValue”对吗?我想停止一个名为记事本的进程,所以我使用:
"notepad" | stop-process
,我得到一个错误。
Get-help stop-process -parameter name
说:管道输入真(ByPropertyName)和“记事本”是“ByPropertyName”?为什么会出现这个错误?谢谢你的帮助
3 回答
如果要通过属性名称将对象的值绑定到参数,则:
- 传递一个具有适当命名属性的对象:
[pscustomobject]@{Name='notepad'} |Stop-Process
# or, for older versions of powershell:
'notepad' |Select @{Name='Name';Expression={$_}} |Stop-Process
- 将管道表达式显式绑定到命名参数:
'notepad' |Stop-Process -Name {$_}
Mathias R. Jessen 的回答提供了一种将字符串(进程名称)管道传输到
Stop-Process
.js2010 的答案正确解释了为什么管道字符串
Stop-Process
不起作用(无需额外的努力),并且还提供了一种有用的技术来跟踪参数绑定,但是 - 在撰写本文时 - 答案包含一些使问题有点混淆的附带信息.
让我提供更详细的解释:
Stop-Process
与 不同Stop-Service
,它的设计目的不是接受字符串(进程名称)作为管道输入。
虽然抽象中的字符串输入仍然可以工作,即如果字符串可以自动转换ByValue
为命令(整个对象)管道绑定参数所期望的数据类型之一,则情况并非如此Stop-Process
,因为进程名称( string) 不能(自动)转换为System.Diagnostics.Process
实例 ( -InputObject
) [1]。
当 PowerShell 在调用期间考虑将管道输入绑定到参数
-Name
时,它会查找具有Name
属性的对象,因为参数声明指定仅当输入对象具有以参数命名的属性时才接受管道输入:在帮助主题中,例如 for
Stop-Process
,这表示为ByPropertyName
。在代码中,它表示为类型的布尔
ValueFromPipelineByPropertyName
属性System.Management.Automation.ParameterAttribute
;也就是说,在PowerShell代码中,参数声明看起来像:ValueFromPipelineByPropertyName
ValueFromPipelineByPropertyName = $true
[Parameter(ValueFromPipelineByPropertyName)] [string[]] $Name
A
[string]
(System.String
) 实例如"alg"
没有Name
属性 - 它本身就是名称。因此,在没有自动将[1]
System.Diagnostics.Process
转换为唯一ByValue
参数的类型的-InputObject
情况下,并且在没有参数的Name
和Id
属性的情况下ByPropertyValue
,调用将失败并显示以下错误消息,这实际上告诉您管道输入是无效(不能绑定到任何参数):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
相比之下,它被设计为接受字符串输入,因为它的-Name
参数(也)被声明为作为一个整体直接接受字符串作为输入对象。
在帮助主题中,例如 for
Stop-Service
,这表示为ByValue
。在 PowerShell 代码中,它表示为
ValueFromPipeline
:
[Parameter(ValueFromPipeline)] [string[]] $Name
笔记:
虽然给定的参数可以是and
ByValue
-ByPropertyValue
这确实是Stop-Service
's-Name
参数的情况 - 这不是典型的。通常,管道绑定参数被声明为标量而不是数组(例如, for
Sort-Object
,-InputObject <PSObject>
而不是-InputObject <PSObject[]>
),这意味着仅支持通过管道传递多个参数,而不是直接参数 - 有关背景信息,请参阅GitHub 问题 #4242。
检查管道绑定参数:
- 命令的给定参数:
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
注意Accept pipeline input?
线;对于非管道绑定参数,您将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
注意:上述技术从给定 cmdlet可能附带的基于 MAML 的帮助文件中收集参数信息(大多数内置cmdlet 都带有此类帮助文件)。虽然帮助文件中的信息应正确反映 cmdlet 的实际参数定义并且通常如此,但不能保证如此。如有疑问,请改用以下技术,直接检查 cmdlet 的实际定义:
# Lists all pipeline-binding parameters defined by the given cmdlet,
# by examining the actual cmdlet definition.
(Get-Command Stop-Process).ParameterSets.Parameters |
Where-Object { $_.ValueFromPipeline -or $_.ValueFromPipelineByPropertyName} |
Select-Object -Unique Name, Aliases, ParameterType, @{
Name = 'Accepts pipeline input'
Expression = {
'True ({0})' -f ($(
if ($_.ValueFromPipeline) { 'ByValue'}
if ($_.ValueFromPipelineByPropertyName) { 'ByPropertyName' }
) -join ', ')
}
} | Sort-Object Name
[1] 除非通过System.Management.Automation.ArgumentTransformationAttribute
派生属性(不常见)声明参数支持自定义类型转换,否则此处适用 PowerShell 的常用转换规则,该规则采用了本答案中讨论的多种技术。在 的情况下System.Diagnostics.Process
,不可能从字符串转换,因为目标类型既没有具有字符串的单参数构造函数,也没有静态.Parse()
方法。可转换性的快速测试是尝试强制转换:失败[System.Diagnostics.Process] 'notepad'
。相比之下,[System.ServiceProcess.ServiceController] 'alg'
有效,因为该类型确实有一个接受 string 的单参数构造函数,但请注意,这种转换不起作用在调用参数绑定期间Stop-Service
,例如'alg' | Stop-Service
- 那里,字符串按原样绑定到ByValue
-Name
参数。
“stop-service -name”可以按值(字符串)传递,所以它使用它。停止进程无法将字符串转换为 -inputobject 的进程类型,即按值管道。“停止进程名称”仅由属性名称提供。
这里还有一些细微差别。可以强制字符串键入 servicecontroller,但不能强制键入 process。因此,理论上可以将字符串作为 -inputobject 用于停止服务,但不能用于停止过程。“stop-service -inputobject alg”也可以,但“stop-process -inputobject notepad”不能。这两个命令之间的不一致可能会令人困惑。
[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".
如果您真的想查看绑定:
trace-command parameterbinding {'alg' | stop-service} -pshost
trace-command parameterbinding {'notepad' | stop-process} -pshost