为什么powershell会思考$dir
是 null
设置位置时而不是写入输出时?
$command = {
param($dir)
Set-Location $dir
Write-Output $dir
}
# run the command as administrator
Start-Process powershell -Verb RunAs -ArgumentList "-NoExit -Command $command 'C:\inetpub\wwwroot'"
这导致以下输出:
Set-Location : Cannot process argument because the value of argument "path" is null. Change the value of argument
"path" to a non-null value.
At line:3 char:2
+ Set-Location $dir
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Location], PSArgumentNullException
+ FullyQualifiedErrorId : ArgumentNull,Microsoft.PowerShell.Commands.SetLocationCommand
C:\inetpub\wwwroot
我也试过:
$command = {
param($dir)
Set-Location $dir
Write-Output $dir
}
$outerCommand = {
Invoke-Command -ScriptBlock $command -ArgumentList 'C:\inetpub\wwwroot'
}
# run the command as administrator
Start-Process powershell -Verb RunAs -ArgumentList "-NoExit -Command $outerCommand"
但后来我得到了:
Invoke-Command : Cannot validate argument on parameter 'ScriptBlock'. The argument is null. Provide a valid value for
the argument, and then try running the command again.
At line:2 char:30
+ Invoke-Command -ScriptBlock $command 'C:\inetpub\wwwroot'
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeCommandCommand
可能的线索:如果我设置一个局部变量而不是使用参数,它会完美地工作:
$command = {
$dir = 'C:\inetpub\wwwroot'
Set-Location $dir
Write-Output $dir
}
# run the command as administrator
Start-Process powershell -Verb RunAs -ArgumentList "-NoExit -Command $command"
类似的 Q/As 并没有完全回答我的问题:
Start-Process
,我需要以管理员身份运行)Invoke-Command
而不是 Start-Process
)最佳答案
$command
是一个脚本块( { ... }
)并且将脚本块字符串化会导致其文字内容 , 不包括封闭的 {
和 }
.
因此,您的可扩展字符串 "-NoExit -Command $command 'C:\inetpub\wwwroot'"
从字面上扩展为以下字符串 - 注意缺少的 { ... }
围绕原始脚本块:
-NoExit -Command
param($dir)
Set-Location $dir
Write-Output $dir
'C:\inetpub\wwwroot'
因丢失附赠
{
和 }
,新powershell
由 Start-Process
产生的进程默默无视孤儿param($dir)
声明,并且鉴于新进程因此没有 $dir
变量(鉴于它也不是自动变量),命令失败,因为 Set-Location $dir
等于Set-Location $null
,失败了。[1]请注意 你永远不能将脚本块传递给
Start-Process
- 所有参数必须是字符串 ,因为只能将字符串传递给外部进程。在您的情况下,最简单的解决方案是:
$command
在您的可扩展字符串中引用 { ... }
以补偿由于串化而造成的 shell 损失 &
以确保在新进程中调用生成的脚本块。 这是一个有效的解决方案:
Start-Process powershell -Verb RunAs -ArgumentList `
"-NoExit -Command & { $command } 'C:\inetpub\wwwroot'"
重要提示:虽然手头的特定脚本块不需要,但具有 的任何脚本块嵌入式
"
字符。不会被正确解析为整体 "..."
的一部分目标进程的字符串 ;为了防止这种情况,他们 必须转义为 \"
,这是外部程序所期望的 - 包括通过其 CLI 的 PowerShell:# Script block with embedded " chars.
$command = {
param($dir)
Set-Location $dir
"Current dir: $dir"
}
# Embed the script block with " escaped as \"
Start-Process powershell -Verb RunAs -ArgumentList `
"-NoExit -Command & { $($command -replace '"', '\"') } 'C:\inetpub\wwwroot'"
[1] 在 Windows PowerShell 中失败;在PowerShell Core中,相当于
Set-Location
不带参数,更改为当前用户的主文件夹。
关于powershell - 使用 Start-Process 使用参数运行脚本 block 命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54994071/