在Powershell中调用批处理脚本时如何传递等号?

16
我们有一个批处理文件,用来调用基于MSBuild的构建过程。语法如下:
build App Target [ Additional MSBuild Arguments ]

在内部,它会执行以下操作:

msbuild.exe %1.msbuild /t:%2 %3 %4 %5 %6 %7 %8 %9

这将导致调用类似于以下方式的MSBuild:

msbuild.exe App.msbuild /t:Target

当任何参数包含等号=时,PowerShell会完全删除它。我的批处理脚本永远看不到它。但在标准的cmd.exe命令提示符中不会发生这种情况。

例如,如果我调用

build App Target "/p:Property=Value"

这是传递给MSBuild的内容:

msbuild.exe App.msmbuild /t:Target /p:Property Value

I expected this:

msbuild.exe App.msbuild /t:Target "/p:Property=Value"

我尝试了Powershell转义字符、标准命令提示符转义字符,甚至是我自己编的东西:

build App Target "/p:Property=Value"
build App Target '/p:Property=Value'
build App Target /p:Property^=Value
build App Target /p:Property`=Value
build App Target /p:Property==Value

没有任何一种方法有效。 我该怎么做才能让等号不被剥离或删除?

6个回答

22

我以前见过这种情况,并找到了一种方法来“欺骗”它。我希望我能解释一下特别是关于“=”的情况,但我不能。在你的情况下,如果你想将属性传递给msbuild,我相当确定以下方法会起作用:

build App Target '"/p:Property=Value"' 

当被回显时,这将产生以下结果:

msbuild.exe App.msbuild /t:Target "/p:Property=Value"

成功了!我原本以为我已经尝试过这种组合了,但我猜只是尝试了单引号而不是在双引号外面包含单引号。有时候Powershell会相当奇怪。 - Aaron Jensen
1
问题在于PowerShell在传递给可执行文件时不会引用参数。因此,即使PowerShell知道“/p:Property=Value”是一个字符串,它也会在没有引号的情况下传递它。这可能会导致可执行文件无法将其视为一个参数。我在使用引号作为参数时遇到了同样的问题,我不得不对它们进行\转义。 - JasonMArcher
@jasonmarcher:同意,但这似乎是唯一的,因为转义'='并没有改变什么。你可以试试看。 - Scott Saad
引用是问题所在,我完全同意你的看法。 - JasonMArcher
重新阅读了你的评论,我明白你的意思了。抱歉,是我误解了。 :) - Scott Saad
太棒了!终于成功获取到需要等号的 Git 构建日期。对于那些感兴趣的人,最终命令是:FOR /F "tokens=1 delims=" %%A IN ('"git show -s --format="%%ci" HEAD"') DO ( @SET BUILD_DATE=%%A ) - Sharken

5

使用 PowerShell 3,你可以使用 --% 停止 PowerShell 正常的解析过程。

build --% App Target "/p:Property=Value"

0

我不确定是否有更简单的答案(我认为没有),但您可以通过使用 .Net 的进程类来调用 cmd.exe 解决该问题。以下是一个例子:

# use .NET Process class to run a batch file, passing it an argument that contains an equals sign. 
# This test script assumes the existence of a batch file "c:\temp\test.bat"
# that has this content:
#      echo %1
#      pause
$cmdLine =  $cmdLine =  '/c c:\temp\test.bat "x=1"'
$procStartInfo =  new-object System.Diagnostics.ProcessStartInfo("cmd", $cmdLine )
$proc = new-object System.Diagnostics.Process
$proc.StartInfo = $procStartInfo
$proc.Start();

这样行不通。调用批处理文件必须是一行操作,正如我在问题中所概述的那样。 - Aaron Jensen
好的,你可以将它制作成一个函数,这样它就可以变成一行代码。但我希望Scott的答案能够奏效。 - Elroy Flynn

0

看起来在 Windows 环境下,只使用单引号包裹双引号可能是最好的选择,适用于多种情况。 微软的以下链接显示了等号的支持(或限制) http://support.microsoft.com/kb/35938 虽然它是针对批处理文件的,但很可能会影响到其他许多微软 shell 产品。


0

你尝试过使用单引号来强制进行字面解释吗?

或者: cmd /c 'msbuild.exe App.msbuild /t:Target "/p:Property=Value"'


调用批处理文件也会删除等号,但在这种情况下,将其括在引号中就足以保留它。 - yoyo

0
答案是%2变成了"/p:property"%3变成了"value"
在您的批处理文件中使用BOTH %2%3,并在它们之间插入一个=符号,使其正常工作。
msbuild.exe %1.msbuild /t:%2=%3 %4 %5 %6 %7 %8 %9

不要在命令行调用中使用引号字符。请使用:

build App Target /p:property=value

如果有其他带有 = 符号的参数,请继续配对它们。

我在一个简单的批处理文件中运行youtube-dl时遇到了同样的问题,因为我传递的URL中有一个 = 符号。 解决方法如下:

@echo off
REM YTDL audio only
echo %1=%2
youtube-dl -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 %1=%2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接