Joh*_*hnF 25 msbuild powershell psake
使用Powershell和Psake为可视化工作室解决方案创建包和部署.尝试使用msbuild部署数据库项目 - 使用msdos visual studio命令行正常工作
msbuild /target:Deploy /p:UseSandboxSettings=false /p:TargetConnectionString="aConnectionWithSpacesAndSemiColons" "aDatabaseProjectPathWithSpaces"
Run Code Online (Sandbox Code Playgroud)
从powershell调用时,相同的方法调用会导致错误
& msbuild /target:Deploy /p:UseSandboxSettings=false /p:TargetConnectionString="aConnectionWithSpacesAndSemiColons" "aDatabaseProjectPathWithSpaces"
Run Code Online (Sandbox Code Playgroud)
与空间有关 - 无法弄清楚如何在powershell中复制此调用 - 示例数据库连接字符串数据源=.\ SQL2008;初始目录= DocumentExecution; Integrated Security = True;
Emp*_*LII 61
如何将包含引号的参数传递给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
Run Code Online (Sandbox Code Playgroud)
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>
当人们在遗留cmd系统和PowerShell之间移动时,调用本机命令会产生相当大的影响(几乎与"使用逗号分隔参数"一样多).
我已经尝试并总结了我在PowerShell(v2和v3)中关于命令调用主题的所有知识,以及我可以集合的所有示例和参考.
1.1)最简单的是,对于位于环境路径中的可执行文件,可以直接调用该命令,就像调用PowerShell cmdlet一样.
PS> Get-ItemProperty echoargs.exe -Name IsReadOnly
...
IsReadOnly : True
PS> attrib echoargs.exe
A R C:\Users\Emperor XLII\EchoArgs.exe
Run Code Online (Sandbox Code Playgroud)
1.2)在环境路径之外,对于特定目录(包括当前目录)中的命令,可以使用命令的完整路径或相对路径.我们的想法是让运算符明确声明"我想调用此文件",而不是让碰巧具有相同名称的任意文件在其位置运行(有关PowerShell安全性的更多信息,请参阅此问题).在需要时未能使用路径将导致"术语无法识别"错误.
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
Run Code Online (Sandbox Code Playgroud)
1.3)如果路径包含特殊字符,则可以使用调用操作符或转义字符.例如,可执行文件以数字开头,或位于包含空格的目录中.
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>
Run Code Online (Sandbox Code Playgroud)
2.1) When you are not typing out a command interactively, but instead have the path stored in a variable, the call operator can also be used to invoke the command named in a variable.
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>
Run Code Online (Sandbox Code Playgroud)
2.2) The arguments passed to a command can also be stored in variables. Arguments in variables can be passed individually, or in an array. For variables containing spaces, PowerShell will automatically escape the spaces so that the native command sees it as a single argument. (Note that the call operator treats the first value as the command and the remaining values as arguments; the arguments should not be combined with the command variable.)
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>
Run Code Online (Sandbox Code Playgroud)
2.3) The array format is especially useful for building up a dynamic list of arguments for a native command. For each argument to be recognized as a distinct parameter, it is important that the arguments get stored in an array variable, and not just munged together in one string. (Note that the common abbreviation $args is an automatic variable in PowerShell, which can cause values saved in it to get overwritten; instead, it is better to use a descriptive name like $msbuildArgs to avoid the naming conflict.)
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>
Run Code Online (Sandbox Code Playgroud)
2.4) Also, for scripts, functions, cmdlets, and the like, PowerShell v2 can send named arguments contained in a hashtable using a technique called "splatting", without having to worry about parameter order. This does not work with native commands, which do not participate in the PowerShell object model and can only handle string values.
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>
Run Code Online (Sandbox Code Playgroud)
3.1) For simple arguments, the automatic escaping used for native commands is generally sufficient. However, for parenthesis, dollar signs, spaces, and such, characters used by PowerShell need to be escaped to be sent as-is to native commands, without having them interpreted by the parser. This can be done with the backtick escape character, `, or by putting the argument inside a single-quote string.
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)>
Run Code Online (Sandbox Code Playgroud)
3.2) Unfortunately, this is not so simple when double quotes are involved. As part of argument processing for native commands, the PowerShell processor attempts to normalize all double quotes in an argument so that the contents of the argument, sans quotes, is passed as a single value to the native command. The native command parameter processing occurs as a separate step after parsing, so normal escaping will not work for double quotes; only escaped single quotes, or backslash-escaped double quotes can be used.
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'>
Run Code Online (Sandbox Code Playgroud)
3.3) PowerShell v3 added a new stop-parsing symbol --% (see about_Parsing). When used before complicated arguments, --% will pass arguments as-is without any parsing or variable expansion, except for cmd-like %ENVIRONMENT_VARIABLE% values.
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>
Run Code Online (Sandbox Code Playgroud)
This can also be used to de-munge a single string representing multiple arguments, by passing the stop-parsing symbol in a string∗ (although the best practice is to not munge arguments in the first place).
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>
Run Code Online (Sandbox Code Playgroud)
There are two key tools for debugging the arguments PowerShell passes to native commands.
4.1) The first is EchoArgs.exe, a console application from the PowerShell Community Extensions that simply writes back the arguments passed to it between angle brackets (as shown in the examples above).
4.2) The second is Trace-Command, a cmdlet that can show many details of how PowerShell processes a pipeline. In particular, the NativeCommandParameterBinder trace source will show what PowerShell receives and passes on to a native command.
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"
Run Code Online (Sandbox Code Playgroud)
Articles
Questions
Tre*_*van 11
如果将Start-Processcmdlet与-ArgumentList参数一起使用,则可以更轻松地完成此操作.我很惊讶这已经没有提到了.
例:
Start-Process -FilePath msbuild.exe -ArgumentList '/target:Deploy /p:UseSandboxSettings=false /p:TargetConnectionString="aConnectionWithSpacesAndSemiColons" "aDatabaseProjectPathWithSpaces"';
Run Code Online (Sandbox Code Playgroud)
这是我喜欢使用的方法,它允许变量替换:
$ConnectionString = 'aConnectionWithSpacesAndSemiColons';
$DatabaseProjectPath = 'aDatabaseProjectPathWithSpaces';
$MsbuildArguments = '/target:Deploy /p:UseSandboxSettings=false /p:TargetConnectionString="{0}" "{1}"' -f $ConnectionString, $DatabaseProjectPath;
Start-Process -FilePath msbuild.exe -ArgumentList $MsbuildArguments;
Run Code Online (Sandbox Code Playgroud)
将整个参数放在单引号中:
& msbuild /target:Deploy /p:UseSandboxSettings=false '/p:TargetConnectionString="aConnectionWithSpacesAndSemiColons"' "aDatabaseProjectPathWithSpaces"
Run Code Online (Sandbox Code Playgroud)
额外的引用级别意味着 PSH 不会按照 PSH 的规则处理内容。(字符串内的任何单引号都需要加倍 - 这是 PSH 单引号字符串中唯一的转义类型)。
| 归档时间: |
|
| 查看次数: |
14096 次 |
| 最近记录: |