即使为 type-casting 提供 [Int32],Powershell 也不会将 Foreach-Object 参数从字符串转换为整数
Powershell not converting Foreach-Object parameter from string to integer even when provided [Int32] for type-casting
如问题标题中所述,我有一个 Powershell one-liner 用于按名称杀死 Application/Process 及其所有相关的 children 进程:
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
但是当我试图用这个 post 中的第一个代码块杀死那些进程时,它会抛出这个错误:
Stop-Process : Cannot bind parameter 'Id'. Cannot convert value ".Id" to type "System.Int32". Error: "Input string was not in a correct format."
所以我确实为 type-conversion 应用了 [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
任何人都可以帮助解决这个问题并通过不过度延长 one-liner 来使 one-liner 正常工作吗??
立即修复:$_.Id
-> `$_.Id
也就是说,您需要防止 up-front 在 expandable (double-quoted) string ("..."
) 中扩展 $_
传递给新的子进程,通过将 $
字符转义为 `$
以便按字面保留它 - 就像你对嵌入的 "
字符所做的那样(`"
- 尽管请注意你没有完全需要引用 Chrome
参数)。
或者,鉴于您的字符串实际上不需要在调用方进行插值,您可以简单地使用 verbatim (single-quoted) string ('...'
),这也避免了转义嵌入的 $
和 "
个字符。:
powershell -c 'Get-Process -Name "Chrome" | Select-Object -Property Id | ForEach-Object -Process { Stop-Process -Id $_.Id -Force }'
退一步:
如果你真的需要调用另一个 PowerShell 实例 - 作为一个昂贵的子进程 - 从 PowerShell,你可以 使用脚本块,这使得转义问题消失,也可能returns - 反序列化 - 对象而不仅仅是 string 输出:
powershell -c { Get-Process -Name "Chrome" | Select-Object -Property Id | ForEach-Object -Process { Stop-Process -Id $_.Id -Force }
注意:如果您需要合并来自 调用方 作用域的值,您需要通过 [=25= 将它们传递给子进程] 范围;一个简化的例子:powershell -c { Write-Output "$args!" } -Args hi
至于缩短命令本身:
powershell -c { Get-Process Chrome | Stop-Process -Force }
上面利用了-Name
隐含作为第一个位置传递参数的目标参数,以及Stop-Process
直接操作的能力在 process-info 通过管道接收的对象上,作为 Get-Process
.
的输出
如问题标题中所述,我有一个 Powershell one-liner 用于按名称杀死 Application/Process 及其所有相关的 children 进程:
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
但是当我试图用这个 post 中的第一个代码块杀死那些进程时,它会抛出这个错误:
Stop-Process : Cannot bind parameter 'Id'. Cannot convert value ".Id" to type "System.Int32". Error: "Input string was not in a correct format."
所以我确实为 type-conversion 应用了 [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
任何人都可以帮助解决这个问题并通过不过度延长 one-liner 来使 one-liner 正常工作吗??
立即修复:$_.Id
-> `$_.Id
也就是说,您需要防止 up-front 在 expandable (double-quoted) string ("..."
) 中扩展 $_
传递给新的子进程,通过将 $
字符转义为 `$
以便按字面保留它 - 就像你对嵌入的 "
字符所做的那样(`"
- 尽管请注意你没有完全需要引用 Chrome
参数)。
或者,鉴于您的字符串实际上不需要在调用方进行插值,您可以简单地使用 verbatim (single-quoted) string ('...'
),这也避免了转义嵌入的 $
和 "
个字符。:
powershell -c 'Get-Process -Name "Chrome" | Select-Object -Property Id | ForEach-Object -Process { Stop-Process -Id $_.Id -Force }'
退一步:
如果你真的需要调用另一个 PowerShell 实例 - 作为一个昂贵的子进程 - 从 PowerShell,你可以 使用脚本块,这使得转义问题消失,也可能returns - 反序列化 - 对象而不仅仅是 string 输出:
powershell -c { Get-Process -Name "Chrome" | Select-Object -Property Id | ForEach-Object -Process { Stop-Process -Id $_.Id -Force }
注意:如果您需要合并来自 调用方 作用域的值,您需要通过 [=25= 将它们传递给子进程] 范围;一个简化的例子:powershell -c { Write-Output "$args!" } -Args hi
至于缩短命令本身:
powershell -c { Get-Process Chrome | Stop-Process -Force }
上面利用了-Name
隐含作为第一个位置传递参数的目标参数,以及Stop-Process
直接操作的能力在 process-info 通过管道接收的对象上,作为 Get-Process
.