powershell - 使用 Start-Process 使用参数运行脚本 block 命令

标签 powershell

为什么powershell会思考$dirnull设置位置时而不是写入输出时?

$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 并没有完全回答我的问题:
  • PowerShell - Start-Process and Cmdline Switches (我不是想用命令行开关运行 exe,我是想用一个需要传递参数的脚本块运行 powershell)
  • How to use powershell.exe with -Command using a scriptblock and parameters (不使用 Start-Process ,我需要以管理员身份运行)
  • Powershell Value of argument path is NULL (使用 Invoke-Command 而不是 Start-Process )
  • 最佳答案

    $command是一个脚本块( { ... } )并且将脚本块字符串化会导致其文字内容 , 不包括封闭的 {} .

    因此,您的可扩展字符串 "-NoExit -Command $command 'C:\inetpub\wwwroot'"从字面上扩展为以下字符串 - 注意缺少的 { ... }围绕原始脚本块:

     -NoExit -Command 
        param($dir)
        Set-Location $dir
        Write-Output $dir
     'C:\inetpub\wwwroot'
    

    因丢失附赠{} ,新powershellStart-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/

    相关文章:

    PowerShell - 如何强制超时调用命令

    powershell - 无法从 Powershell 将 Chrome 设置为默认浏览器

    powershell - 新的pnp站点的Powershell PnP命令出现错误

    powershell - 使用 Powershell 更改 DCOM 配置安全设置

    powershell - 如何从 Remove-Item 中捕获错误并发出警告?

    .net - ScriptBlock 未在 PowerShell 中执行

    powershell - 相当于C# “is”运算符的PowerShell?

    windows - Powershell 获取 Windows 中显示的区分大小写的路径

    sql - 找不到与参数名称 'ConnectionString' 匹配的参数

    python - 如何在 powershell 和 python 脚本中保护 API 身份验证详细信息