为什么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"
类似的问/答未能完全回答我的问题:
Start-Process
,我需要以管理员身份运行)Invoke-Command
而不是Start-Process
)答案 0 :(得分:2)
$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
变量(假设它也不是 automatic 变量),命令失败,因为Set-Location $dir
等于{{1} },失败。 [1]
请注意,您永远不能将脚本块这样传递给Set-Location $null
-所有参数都必须为 strings ,因为只有字符串可以传递给外部流程。
您遇到的最简单的解决方案是:
将Start-Process
引用括在$command
的可扩展字符串中,以补偿由于字符串化导致的此附件丢失
和附加{ ... }
,以确保在新过程中调用生成的脚本块。
这是一个可行的解决方案:
&
重要:虽然手边的特定脚本块并不需要,但是任何已嵌入Start-Process powershell -Verb RunAs -ArgumentList `
"-NoExit -Command & { $command } 'C:\inetpub\wwwroot'"
个字符的脚本块。不会被目标进程正确解析为整个"
字符串的一部分;为防止这种情况,它们必须以"..."
的形式转义,这是外部程序所期望的-包括通过CLI进行的PowerShell:
\"
[1]在 Windows PowerShell 中失败;在PowerShell Core 中,它等于# 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 :(得分:0)
我遇到了类似的问题,但我想将 Start-Process -ArgumentList
所需的所有命令放入一个变量中。感谢上面mklement0
的回答,我设法找到了解决方案。
这里有一个稍微替代的答案,它在 -Command
[powershell.exe
] [link 1 ]:
Here-String