通过PowerShell Start-Process将多变量命令行传递给cmd.exe

qc6wkl3g  于 2023-05-18  发布在  Shell
关注(0)|答案(2)|浏览(230)

我正试图通过cmd.exe多变量命令行的代码是在PowerShell脚本中运行的较大脚本的一部分。
下面的代码无法传递正确的参数。

$msbuild = "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\msbuild.exe"
$buildCommand = 'C:\Git\Asd\build\XDA_2019.sln /m /t:Build /p:Configuration=Debug /p:Platform="ASX Platform"'
Write-Host "buildCommand: $buildCommand"
Write-Host "msbuild: $msbuild"

$startProcessArgs = @('/c', $msbuild, $buildCommand)
Start-Process -FilePath cmd.exe -ArgumentList $startProcessArgs -PassThru -Wait -NoNewWindow

错误

buildCommand: C:\CamtekGit\BIS\build\Falcon_2019.sln /m /t:Build /p:Configuration=Debug /p:Platform="Eagle Platform"
msbuild: C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\msbuild.exe
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.

尝试在cmd中直接运行命令,它可以工作cmd.exe也读取并无法修复它Powershell: Start-Process doesn't pass arguments to cmd.exeRunning cmd.exe through start-process but unable to pass the command to cmd.exe
谢谢你的帮助

nzkunb0c

nzkunb0c1#

试试用

$msbuild = 'CALL "C:\Program Files\..."'
kjthegm6

kjthegm62#

要在当前窗口中同步执行控制台应用程序或批处理文件,请 * 直接 * 调用它们,不要 * 使用Start-Process(或其所基于的System.Diagnostics.Process API)-参见this answer
GitHub docs issue #6239提供了何时使用Start-Process是合适的和不合适的指导。
直接执行不允许您直接捕获外部程序的输出,它还将其进程退出代码反映在自动$LASTEXITCODE变量中。
因此:

cmd /c "`"$msbuild`" $buildCommand"

注意,在传递给cmd.exe的命令行中,需要在可执行路径上使用 embedded 双引号,因为它包含 * 空格 *。
他们的有效缺席也是由您的Start-Process呼叫中的问题引起的:

  • 不幸的是,Start-Process中的long-standing bug需要使用包含空格的 embedded 双引号环绕参数,例如:-ArgumentList '-foo', '"bar baz"'
  • 因此,通常更好地将所有参数编码在 * 单个字符串 * 中,例如:-ArgumentList '-foo "bar baz"',因为使用嵌入式双引号的情景需求是显而易见的。详细信息请参见this answer

在您的特定情况下,您可以按照如下方式使Start-Process调用工作:

$startProcessArgs = "/c `"`"$msbuild`" $buildCommand`""

注意:这是可行的-尽管 * double * 嵌套的"字符没有转义。- 是X1 M11 N1 X在引用时的“怪癖”的证明。

退一步

  • msbuild.exe作为任何外部程序,也可以直接从PowerShell调用。然而,在幕后,PowerShell将/p:Platform="ASX Platform"等参数转换为"/p:Platform=ASX Platform",而msbuild.exe可能无法理解。
  • 有几种变通方法,通过cmd /c调用在概念上是最干净的。
  • 另一个是使用--%,停止解析标记,但它附带severe limitations
& "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\msbuild.exe" C:\Git\Asd\build\XDA_2019.sln /m /t:Build /p:Configuration=Debug --% /p:Platform="ASX Platform"
& "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\msbuild.exe" C:\Git\Asd\build\XDA_2019.sln /m /t:Build /p:Configuration=Debug '/p:Platform="ASX Platform"'
  • 另一种方法--具有使用Start-Process的所有缺点--是使用Start-Process * 直接 * 调用msbuild.exe(而不是通过cmd.exe),在您的情况下,这将简化您的调用:
Start-Process -FilePath $msbuild -ArgumentList $buildCommand -PassThru -Wait -NoNewWindow

相关问题