1

如问题标题中所述,我有一个 Powershell 单行程序,用于按名称杀死应用程序/进程及其所有相关子进程:

powershell -c "Get-Process -Name `"Chrome`" | Select-Object -Property Id | ForEach-Object -Process { Stop-Process -Id $_.Id -Force }"

当我通过删除进程终止代码并仅打印进程 ID 进行测试时,它可以正常工作,如下所示:

powershell -c "Get-Process -Name `"Chrome`" | Select-Object -Property Id"

这会将与 Chrome 实例相关的所有 ID 显示为:

372
1232
1776
1884
2024
2676
3008
3240

但是当我试图用这篇文章中的第一个代码块杀死这些进程时,它会抛出这个错误:

Stop-Process : Cannot bind parameter 'Id'. Cannot convert value ".Id" to type "System.Int32". Error: "Input string was not in a correct format."

所以我确实应用了 [Int32] 进行类型转换,认为这足以将 ID 以有效格式带入 Stop-Process 部分并杀死它,但这也不起作用:

powershell -c "Get-Process -Name `"Chrome`" | Select-Object -Property Id | ForEach-Object -Process { Stop-Process -Id [Int32]($_.Id) -Force }"

这会引发错误:

The term '.Id' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if
a path was included, verify that the path is correct and try again.
At line:1 char:108
+ ... y Id | ForEach-Object -Process { Stop-Process -Id [Int32](.Id) -Force ...
+                                                               ~~~
    + CategoryInfo          : ObjectNotFound: (.Id:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

任何人都可以帮助解决这个问题并通过不要过度拉长单线来使单线工作吗?

4

1 回答 1

4

立即修复:- $_.Id>`$_.Id

也就是说,您需要防止在传递给新子进程的可扩展(双引号)字符串 ( )内部进行预先扩展,方法是转义字符,以便从字面上保留它 - 就像您使用嵌入的字符(- 尽管请注意,您根本不需要引用参数)。$_"..."$`$"`"Chrome

或者,鉴于您的字符串实际上不需要在调用方进行插值,您可以简单地使用逐字(单引号)字符串 ( '...'),这也避免了转义嵌入$"字符的需要:

powershell -c 'Get-Process -Name "Chrome" | Select-Object -Property Id | ForEach-Object -Process { Stop-Process -Id $_.Id -Force }'

退后一步:

如果您确实需要从 PowerShell调用另一个 PowerShell 实例(作为昂贵的子进程),则可以使用脚本块,这会使转义问题消失,并且还可能返回 - 反序列化的对象,而不仅仅是字符串输出:

powershell -c { Get-Process -Name "Chrome" | Select-Object -Property Id | ForEach-Object -Process { Stop-Process -Id $_.Id -Force }

注意:如果您需要合并调用者范围内的值,则需要通过-Args参数将它们传递给子进程;一个简化的例子:powershell -c { Write-Output "$args!" } -Args hi


至于缩短命令本身

powershell -c { Get-Process Chrome | Stop-Process -Force }

以上利用了作为第一个位置-Name传递参数的目标参数的隐含,以及直接对通过管道接收到的进程信息对象进行操作的能力,作为.Stop-ProcessGet-Process

于 2022-02-02T21:06:42.090 回答