【问题标题】:How do I pass an equal sign when calling a batch script in Powershell?在 Powershell 中调用批处理脚本时如何传递等号?
【发布时间】:2011-02-09 01:05:49
【问题描述】:

我们有一个调用基于 MSBuild 的构建过程的批处理文件。语法:

build App Target [ Additional MSBuild Arguments ]

在内部,它这样做:

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

这导致对 MSBuild 的调用如下所示:

msbuild.exe 应用程序.msbuild /t:目标

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

例如,如果我调用

build App Target "/p:Property=Value"

这是传递给 MSBuild 的内容:

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

我预料到了:

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

这些都不起作用。 我该怎么做才能使等号不被剥离或删除?

【问题讨论】:

    标签: powershell batch-file


    【解决方案1】:

    使用PowerShell 3,您可以使用 --% 来停止 powershell 的正常解析。

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

    【讨论】:

      【解决方案2】:

      我以前见过这个,并找到了一种欺骗它的方法。我希望我能解释一下“=”是怎么回事,但我不能。在您的情况下,如果您想将属性传递给 msbuild,我相当肯定以下方法会起作用:

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

      当回显时,这会产生以下内容:

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

      【讨论】:

      • 成功了!我以为我尝试了这种组合,但我想我只尝试了单引号,而不是双引号周围的单引号。 Powershell 有时会很奇怪。
      • 问题是 PowerShell 在传递给可执行文件时不引用参数。因此,即使 PowerShell 知道 "/p:Property=Value" 是一个字符串,它也会在不带引号的情况下传递它。这可能会导致可执行文件不将其视为一个参数。我在参数中包含引号时遇到了同样的问题,我不得不 \ 转义它们。
      • @jasonmarcher:同意,但这似乎是唯一的 '=' 因为转义它没有任何区别。试试看,你会看到的。
      • 引用是问题,我完全同意你的看法。
      • 重新阅读您的评论后,我明白您的意思了。对不起,我的误解。 :)
      【解决方案3】:

      我不知道是否有更简单的答案(我认为没有),但您可以通过使用 .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();
      

      【讨论】:

      • 这行不通。如我的问题所述,调用批处理文件必须是单行操作。
      • 好吧,你可以把它变成一个函数,然后它可以是一个单行。但我希望斯科特的回答有效。
      【解决方案4】:

      您是否尝试过单引号来强制进行字面解释?

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

      【讨论】:

      • 调用批处理文件也会去掉 = 符号,但在这种情况下,用引号括起来就足以保留它。
      【解决方案5】:

      似乎只有双引号周围的单引号可能最适合 Windows 环境周围的多个场景。 MS的以下链接显示了它对等号的支持(或限制) http://support.microsoft.com/kb/35938 它特定于批处理文件,但它可能会影响许多其他 MS shell 产品。

      【讨论】:

        【解决方案6】:

        答案是%2变成"/p:property"%3变成"value"

        通过同时使用%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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-05-22
          • 2013-07-30
          • 1970-01-01
          • 1970-01-01
          • 2023-01-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多