如何通过Start-Process向pwsh传递带参数的脚本块?
使用Start-Process传递带参数的PowerShell脚本块的最佳实践
问题场景
直接执行以下pwsh命令时,能正常输出内容并遵守-NoExit参数:
pwsh -command $([scriptblock]::Create('param($p1,$p2) write-host $p1 $p2; write-host ''hello'' $p2; pause;')) -args 'hi', 'world' -NoExit
输出:
hi world hello world Press Enter to continue...
但通过Start-Process执行时,程序会立即退出(忽略-NoExit)并报错:
Start-Process -FilePath "pwsh" -Wait -WindowStyle Maximized -ArgumentList @("-command",$([scriptblock]::Create('param($p1,$p2) write-host $p1 $p2; write-host ''hello'' $p2; pause;')), '-args', 'hi', 'world', '-NoExit')
错误信息:
hello Press Enter to continue... : -args: The term 'args' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
核心原因
Start-Process的ArgumentList会将数组中的每个元素作为独立的命令行参数传递给pwsh.exe。此时-args被当成了脚本块内部的命令,而非pwsh.exe的顶层参数,导致识别失败;同时-NoExit也未被正确识别,程序执行完脚本后直接退出。
最佳实践方案
方案1:使用EncodedCommand避免转义问题
这是最可靠的方式,通过Base64编码整个执行逻辑,彻底规避引号和参数拆分的问题:
# 定义要执行的脚本块 $targetScript = { param($p1, $p2) Write-Host $p1 $p2 Write-Host 'hello' $p2 pause } # 构建完整的命令字符串(包含脚本块调用和参数) $commandToRun = "& $targetScript 'hi' 'world'" # 将命令编码为PowerShell要求的UTF-16LE Base64格式 $encodedCommand = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($commandToRun)) # 通过Start-Process调用pwsh,传递编码后的命令和-NoExit参数 Start-Process -FilePath "pwsh" -Wait -WindowStyle Maximized -ArgumentList @("-EncodedCommand", $encodedCommand, "-NoExit")
方案2:将脚本逻辑与参数整合为单个-command参数
如果不想使用编码,可以将脚本块、参数调用整合成一个字符串,作为-command的单一参数传递:
Start-Process -FilePath "pwsh" -Wait -WindowStyle Maximized -ArgumentList @( "-command", "& { param(`$p1,`$p2) Write-Host `$p1 `$p2; Write-Host 'hello' `$p2; pause; } 'hi' 'world'", "-NoExit" )
注意:这里需要对脚本块内的变量$进行转义(`$),避免被当前PowerShell会话提前解析。
效果验证
执行上述任一方案后,新弹出的pwsh窗口会正常输出:
hi world hello world Press Enter to continue...
按下回车后,窗口会保持打开(遵守-NoExit参数)。
内容的提问来源于stack exchange,提问作者sandthorn
相关产品推荐
相关产品推荐

