gpt4 book ai didi

powershell - Powershell调用带嵌套引号的msbuild

转载 作者:行者123 更新时间:2023-12-03 02:10:06 24 4
gpt4 key购买 nike

使用Powershell和Psake为Visual Studio解决方案创建打包和部署。
尝试使用msbuild部署数据库项目-使用msdos visual studio命令行可以正常工作

   msbuild /target:Deploy /p:UseSandboxSettings=false /p:TargetConnectionString="aConnectionWithSpacesAndSemiColons" "aDatabaseProjectPathWithSpaces"

从Powershell调用相同的方法会导致错误
& msbuild /target:Deploy /p:UseSandboxSettings=false /p:TargetConnectionString="aConnectionWithSpacesAndSemiColons" "aDatabaseProjectPathWithSpaces"

与空格有关-无法弄清楚如何在Powershell中复制此调用-示例数据库连接字符串
数据源=。\ SQL2008;初始目录= DocumentExecution;集成安全性= True;

最佳答案

简洁版本

如何将包含引号的参数传递给PowerShell的本机命令?

  • 在参数字符串中使用单引号而不是双引号:"/p:Target='Data Source=(local)\SQL;Integrated Security=True'"/p:Target='Data Source=(local)\SQL;Integrated Security=True'
  • 在参数字符串中对双引号使用反斜杠转义:'/p:Target=\"Data Source=(local)\SQL;Integrated Security=True\"'/p:Target="Data Source=(local)\SQL;Integrated Security=True"

  • 如果嵌入式引号仅用于将参数视为单个字符串,而不是参数的必需部分,则可以使用以下内容:
  • 引用整个参数字符串,而不是在参数中嵌入引号:'/p:Target=Data Source=(local)\SQL;Integrated Security=True'/p:Target=Data Source=(local)\SQL;Integrated Security=True
  • 用反引号转义所有PowerShell特殊字符(只能作为嵌入式参数来完成):/p:Target=`"Data Source=`(local`)\SQL`;Integrated Security=True`"/p:Target=Data` Source=`(local`)\SQL`;Integrated` Security=True/p:Target=Data Source=(local)\SQL;Integrated Security=True

  • 完整的命令行示例(使用第二种替代方法):

    PS> [string[]]$arguments = @(
    '/target:Deploy',
    '/p:UseSandboxSettings=False',
    '/p:TargetDatabase=UpdatedTargetDatabase',
    '/p:TargetConnectionString=\"Data Source=(local)\SQL;Integrate Security=True\"',
    'C:\program files\MyProjectName.dbproj'
    )
    PS> ./echoargs $arguments
    Arg 0 is </target:Deploy>Arg 1 is </p:UseSandboxSettings=False>Arg 2 is </p:TargetDatabase=UpdatedTargetDatabase>Arg 3 is </p:TargetConnectionString="Data Source=(local)\SQL;Integrate Security=True">Arg 4 is <C:\program files\MyProjectName.dbproj>



    Long Version

    Calling native commands is something that crops up quite a bit as folks move between the legacy cmd system and PowerShell (almost as much as the "separating parameters with commas" gotcha ;).

    I've tried and sum up everything I know on the subject of command invocation in PowerShell (v2 and v3) here, along with all the examples and references I can muster.


    1) Calling Native Commands Directly

    1.1) At its simplest, for an executable located in the environment path, the command can be called directly, just as you would call a PowerShell cmdlet.

    PS> Get-ItemProperty echoargs.exe -Name IsReadOnly
    ...
    IsReadOnly : True

    PS> attrib echoargs.exe
    A R C:\Users\Emperor XLII\EchoArgs.exe

    1.2)在环境路径之外, 用于特定目录(包括当前目录)中的命令,该命令的完整或相对路径可用于。这个想法是让运算符(operator)显式声明“我要调用此文件”,而不是让碰巧具有相同名称的任意文件在其位置( see this question for more info on PowerShell security)运行。如果在需要时未使用路径,将导致“无法识别术语”错误。

    PS> echoargs arg
    The term 'echoargs' is not recognized as the name of a cmdlet, function, script file,
    or operable program...

    PS> ./echoargs arg
    Arg 0 is <arg>

    PS> C:\Windows\system32\attrib.exe echoargs.exe
    A R C:\Users\Emperor XLII\EchoArgs.exe

    1.3)如果路径包含特殊字符,则可以在中使用 call 操作符或转义字符。例如,以数字开头或位于包含空格的目录中的可执行文件。

    PS> $env:Path
    ...;C:\tools\;...

    PS> Copy-Item EchoArgs.exe C:\tools\5pecialCharacter.exe
    PS> 5pecialCharacter.exe special character
    Bad numeric constant: 5.

    PS> & 5pecialCharacter.exe special character
    Arg 0 is <special>
    Arg 1 is <character>

    PS> `5pecialCharacter.exe escaped` character
    Arg 0 is <escaped character>


    PS> C:\Users\Emperor XLII\EchoArgs.exe path with spaces
    The term 'C:\Users\Emperor' is not recognized as the name of a cmdlet, function,
    script file, or operable program...

    PS> & 'C:\Users\Emperor XLII\EchoArgs.exe' path with spaces
    Arg 0 is <path>
    Arg 1 is <with>
    Arg 2 is <spaces>

    PS> C:\Users\Emperor` XLII\EchoArgs.exe escaped` path with` spaces
    Arg 0 is <escaped path>
    Arg 1 is <with spaces>

    2)间接调用本机命令

    2.1)当您不是交互式地键入命令,而是将路径存储在变量 中时,调用运算符也可以用于调用以变量命名的命令。

    PS> $command = 'C:\Users\Emperor XLII\EchoArgs.exe'
    PS> $command arg
    Unexpected token 'arg' in expression or statement.

    PS> & $command arg
    Arg 0 is <arg>

    2.2)传递给命令的参数也可以存储在变量中。 变量中的参数可以单独或以数组形式传递。 对于包含空格的变量,PowerShell将自动转义空格,以便本机命令将其视为单个参数。 (请注意,调用运算符将​​第一个值视为命令,将其余值视为参数;这些参数不应与命令变量组合。)

    PS> $singleArg = 'single arg'
    PS> $mushedCommand = "$command $singleArg"
    PS> $mushedCommand
    C:\Users\Emperor XLII\EchoArgs.exe single arg

    PS> & $mushedCommand
    The term 'C:\Users\Emperor XLII\EchoArgs.exe single arg' is not recognized as the
    name of a cmdlet, function, script file, or operable program...

    PS> & $command $singleArg
    Arg 0 is <single arg>

    PS> $multipleArgs = 'multiple','args'
    PS> & $command $multipleArgs
    Arg 0 is <multiple>
    Arg 1 is <args>

    2.3)数组格式对于为本地命令建立动态参数列表特别有用。 对于每个要被识别为不同参数的参数,重要的是将这些参数存储在数组变量中,而不仅仅是将它们混合在一个字符串中。 (请注意,常用缩写 $args是PowerShell中的一个自动变量,它可能导致保存在其中的值被覆盖;相反,最好使用诸如 $msbuildArgs之类的描述性名称,以避免命名冲突。)

    PS> $mungedArguments = 'initial argument'
    PS> $mungedArguments += 'second argument'
    PS> $mungedArguments += $(if( $someVariable ) { 'dynamic A' } else { 'dynamic B' })
    PS> ./echoargs $mungedArguments
    Arg 0 is <initial argumentsecond argumentdynamic B>

    PS> $arrayArguments = @('initial argument')
    PS> $arrayArguments += 'second argument'
    PS> $arrayArguments += $(if( $someVariable ) { 'dynamic A' } else { 'dynamic B' })
    PS> ./echoargs $arrayArguments
    Arg 0 is <initial argument>
    Arg 1 is <second argument>
    Arg 2 is <dynamic B>

    2.4)同样,对于脚本,函数,cmdlet等,PowerShell v2可以使用称为“splatting”的技术发送哈希表中包含的命名参数,而不必担心参数顺序。这不适用于本机命令,本机命令不参与PowerShell对象模型,并且只能处理字符串值。

    PS> $cmdletArgs = @{ Path = 'EchoArgs.exe'; Name = 'IsReadOnly' }
    PS> $cmdlet = 'Get-ItemProperty'
    PS> & $cmdlet $cmdletArgs # hashtable object passed to cmdlet
    Cannot find path 'C:\Users\Emperor XLII\System.Collections.Hashtable'...

    PS> & $cmdlet @cmdletArgs # hashtable values passed to cmdlet
    ...
    IsReadOnly : True

    PS> ./echoargs @cmdletArgs
    Arg 0 is <Name>
    Arg 1 is <IsReadOnly>
    Arg 2 is <Path>
    Arg 3 is <EchoArgs.exe>

    3)调用带有复杂参数的本机命令

    3.1)对于简单参数,用于本机命令的自动转义通常就足够了。但是,对于括号,美元符号,空格等,PowerShell使用的 字符需要进行转义以按原样发送给本地命令,而无需解析器对其进行解释。这可以通过反引号转义字符 `或通过将参数放在单引号字符串内来完成。

    PS> ./echoargs money=$10.00
    Arg 0 is <money=.00>

    PS> ./echoargs money=`$10.00
    Arg 0 is <money=$10.00>


    PS> ./echoargs value=(spaces and parenthesis)
    The term 'spaces' is not recognized as the name of a cmdlet, function, script file,
    or operable program...

    PS> ./echoargs 'value=(spaces and parenthesis)'
    Arg 0 is <value=(spaces and parenthesis)>

    3.2)不幸的是,当涉及到双引号时,这并不是那么简单。作为本机命令的参数处理的一部分,PowerShell处理器尝试对参数中的所有双引号进行规范化,以便将参数的内容(无引号)作为单个值传递给本机命令。解析后,本机命令参数处理是作为单独的步骤进行的,因此 常规转义不适用于双引号。只能使用转义的单引号或反斜杠的双引号

    PS> ./echoargs value="double quotes"
    Arg 0 is <value=double quotes>

    PS> ./echoargs 'value="string double quotes"'
    Arg 0 is <value=string>
    Arg 1 is <double>
    Arg 2 is <quotes>

    PS> ./echoargs value=`"escaped double quotes`"
    Arg 0 is <value=escaped double quotes>

    PS> ./echoargs 'value=\"backslash escaped double quotes\"'
    Arg 0 is <value="backslash escaped double quotes">


    PS> ./echoargs value='single quotes'
    Arg 0 is <value=single quotes>

    PS> ./echoargs "value='string single quotes'"
    Arg 0 is <value='string single quotes'>

    PS> ./echoargs value=`'escaped` single` quotes`'
    Arg 0 is <value='escaped single quotes'>

    3.3) PowerShell v3添加了新的停止分析符号 --%(请参阅 about_Parsing )。当在复杂参数之前使用时, --%将按原样传递参数,而不进行任何解析或变量扩展,除了类似cmd的%ENVIRONMENT_VARIABLE%之外。

    PS> ./echoargs User:"$env:UserName" "Hash"#555
    Arg 0 is <User:Emperor XLII>
    Arg 1 is <Hash>

    PS> ./echoargs User: "$env:UserName" --% "Hash"#555
    Arg 0 is <User:Emperor XLII>
    Arg 1 is <Hash#555>

    PS> ./echoargs --% User: "%USERNAME%" "Hash"#555
    Arg 0 is <User:Emperor XLII>
    Arg 1 is <Hash#555>

    通过在字符串 中传递停止分析符号,这也可以用于消除代表多个参数的单个字符串的干扰(尽管最佳做法是首先不要消除参数)。

    PS> $user = 'User:"%USERNAME%"'
    PS> $hash = 'Hash#' + $hashNumber
    PS> $mungedArguments = $user,$hash -join ' '
    PS> ./echoargs $mungedArguments
    Arg 0 is <User:%USERNAME% Hash#555>

    PS> ./echoargs --% $mungedArguments
    Arg 0 is <$mungedArguments>

    PS> ./echoargs '--%' $mungedArguments
    Arg 0 is <User:Emperor XLII>
    Arg 1 is <Hash#555>

    4)调试本机命令

    有两个用于调试PowerShell传递给本机命令的参数的关键工具。

    4.1)第一个是 EchoArgs.exe ,它是 PowerShell Community Extensions的控制台应用程序,它简单地写回在尖括号之间传递给它的参数(如上面的示例所示)。

    4.2)第二个是 Trace-Command ,它是一个cmdlet,可以显示PowerShell如何处理管道的许多详细信息。特别是, NativeCommandParameterBinder跟踪源将显示PowerShell接收并传递给本机命令的内容。

    PS> Trace-Command *NativeCommand* { ./echoargs value="double quotes" } -PSHost
    DEBUG: NativeCommandParameterBinder : Raw argument string: "value=double quotes"
    DEBUG: NativeCommandParameterBinder : Argument 0: value=double quotes

    PS> Trace-Command *NativeCommand* { ./echoargs 'value="double quotes"' } -PSHost
    DEBUG: NativeCommandParameterBinder : Raw argument string: "value="double quotes""
    DEBUG: NativeCommandParameterBinder : Argument 0: value=double
    DEBUG: NativeCommandParameterBinder : Argument 1: quotes

    PS> Trace-Command *NativeCommand* { ./echoargs value=`"double quotes`" } -PSHost
    DEBUG: NativeCommandParameterBinder : Raw argument string: value="double quotes"
    DEBUG: NativeCommandParameterBinder : Argument 0: value=double quotes

    PS> Trace-Command *NativeCommand* { ./echoargs 'value=\"double quotes\"' } -PSHost
    DEBUG: NativeCommandParameterBinder : Raw argument string: "value=\"double quotes\""
    DEBUG: NativeCommandParameterBinder : Argument 0: value="double quotes"

    其他资源

    文章
  • 2012-01-02-PowerShell V3 CTP2 Provides Better Argument Passing to EXEs
  • 2011-03-10-The problem with calling legacy/native apps from PowerShell
  • 2010-11-04-Escaping Spaces
  • 2010-02-01-The trials and tribulations of using MSDeploy with PowerShell
  • 2008-10-17-Executing commands which require quotes and variables is practically impossible [Connect]
  • 2006-05-15-Cannot enter an argument containing double quotes [Connect]

  • 问题
  • 2013-09-11-powershell executing external command not accepting parameter
  • 2013-02-20-Parameters with double quotes are not properly passed to Scriptblock by ArgumentList
  • 2013-01-02-ERROR: Description = Invalid query
  • 2012-09-18-How can I execute an external program with parameters in PowerShell?
  • 2012-09-10-Invoke executable (w/parameters) from powershell script
  • 2012-08-16-How do I pass a property value containing a semicolon on the MSBuild command line when running it from PowerShell?
  • 2012-08-08-Call ruby script from powershell
  • 2012-08-01-Brackets or quotation marks breaking a powershell command
  • 2012-07-13-Problems using powershell to perform a source safe get by label
  • 2012-06-13-Missing argument -m using svn at windows powershell
  • 2012-06-01-Powershell command line argument with spaces and curly brackets?
  • 2012-04-18-Spaced paths, msbuild, and psake
  • 2012-04-12-Make Power shell ignore semicolon
  • 2012-03-08-Simple Powershell Msbuild with parameter fails
  • 2012-02-10-Quote Madness in Powershell
  • 2012-01-18-Powershell: run msiexec with dynamically created parameters
  • 2012-01-18-PowerShell's call operator (&) syntax and double-quotes
  • 2012-01-16-PowerShell - passing calculated paths with spaces
  • 2012-01-09-powershell: script to start a program with parameters?
  • 2011-12-20-Powershell - calling icacls with parantheses included in parameters
  • 2011-12-15-Msbuild log doesn't work when executed through powershell
  • 2011-12-06-Pass parameters to InstallUtil from Powershell
  • 2011-11-23-Executing an exe with arguments using Powershell
  • 2011-11-08-Powershell remove quotes when start process
  • 2011-09-16-Commands executed in PowerShell with variables surrounded in quotes fail. Why?
  • 2011-07-25-Powershell parsing quotes strangely(答案中包括a short analysis of quote parsing)
  • 2011-07-15-powershell stripping double quotes from command line arguments
  • 2011-06-14-In Powershell, how do you execute an arbitrary native command from a string?
  • 2011-06-03-Powershell call msbuild with nested quotation marks
  • 2011-05-13-powershell - passing parameters to exe
  • 2011-03-02-Why does this PowerShell script fail to execute this external command properly?
  • 2011-01-09-Executing an EXE file using powershell script
  • 2010-12-13-Command-line arguments to an exe
  • 2010-10-08-What is up with this PowerShell command line quoting/escaping?
  • 2010-10-05-Running an exe using powershell from a directory with spaces in it
  • 2010-08-28-Executing a Command stored in a Variable from Powershell
  • 2010-08-17-How do you call msdeploy from powershell when the parameters have spaces?
  • 2010-04-12-How to suppress quotes in Powershell commands to executables
  • 2010-01-26-powershell sending multiple parameter to a external command
  • 2009-11-04-How to run exe in powershell with parameters with spaces and quotes
  • 2009-03-16-PowerShell - Start-Process and Cmdline Switches
  • 2009-01-14-How to escape command line arguments on Powershell?
  • 关于powershell - Powershell调用带嵌套引号的msbuild,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6224638/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com