当参数有空格时,如何从 powershell 调用 msdeploy?

发布于 2024-09-15 08:30:31 字数 2473 浏览 7 评论 0原文

我在尝试从 powershell 脚本发送到 msdeploy 的参数中遇到了空格问题。

还有许多其他相关文章,但都没有解决问题。
使用 Power Shell 和 MSDeploy 时出现问题。
类似的SO问题不起作用:如何在 powershell 中使用带有空格和引号的参数运行 exe
PowerShell 错误: 执行需要引号和变量的命令实际上是不可能的
另一个不起作用的 SO 问题:在 PowerShell 2.0 中传递参数

最简单的例子,成功但当我让它变得更复杂时失败,就是转储默认网站。

$msdeploy = "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe"
&$msdeploy -verb:dump -source:appHostConfig=`'默认网站`' -verbose
==成功

这个?

$sitename="默认网站"
&$msdeploy -verb:dump -source:appHostConfig=$sitename -verbose
==失败并出现以下错误
msdeploy.exe:错误:无法识别参数 '"-source:"appHostConfig=default'。所有参数必须以“-”开头。
位于 C:\xxx\test.ps1:122 字符:6
+&
+ CategoryInfo:未指定:(错误:无法识别...以“-”开头。:字符串)[],RemoteException
+FullyQualifiedErrorId:NativeCommandError
错误计数:1。

以下变体也失败了
#失败
$sitename=`'默认网站`'
$sitename=`'"默认网站"`'
$sitename="`'默认网站`'"
$sitename="默认网站"
$sitename="'默认网站'"

&$msdeploy -verb:dump "-source:appHostConfig=$sitename" -verbose
&$msdeploy -verb:dump -source:appHostConfig="$sitename" -verbose
&$msdeploy -verb:dump -source:appHostConfig='$sitename' -verbose
&$msdeploy -verb:dump -source:appHostConfig=`'$sitename`' -verbose
&$msdeploy -verb:dump -source:appHostConfig=`"$sitename`" -verbose

我不知所措。和我一起工作的每个人都不知所措。说真的,这很糟糕。我喜欢 Powershell。我喜欢 msdeploy。我不能说我喜欢把它们放在一起。看起来专注于 API 而不是 cli 可能更容易。

编辑:

皇帝四十二建议的字符串数组中的参数效果很好。以下文章中提供了替代解决方案: 将 MSDeploy 与 PowerShell 结合使用的考验和磨难

function PushToTarget([string]$server, [string]$remotePath, [string]$localPath) {
    cmd.exe /C $("msdeploy.exe -verb:sync -source:contentPath=`"{0}`" -dest:computerName=`"{1}`",contentPath=`"{2}`" -whatif" -f $localPath, $server, $remotePath )
}

I'm running into a problem with spaces in my parameters that I try to send into msdeploy from a powershell script.

There are a number of other related articles but none of them solve the problem.

Problems Using Power Shell And MSDeploy.

Similar SO issue that doesn't work: How to run exe in powershell with parameters with spaces and quotes

PowerShell BUG: Executing commands which require quotes and variables is practically impossible

Another SO issue that doesn't work:Passing parameters in PowerShell 2.0

The simplest example that succeeds and then fails when I make it more complicated is just dumping the default web site.

$msdeploy = "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe"

&$msdeploy -verb:dump -source:appHostConfig=`'default web site`' -verbose

==SUCCESS

This one?

$sitename="default web site"

&$msdeploy -verb:dump -source:appHostConfig=$sitename -verbose

==FAIL with the following error

msdeploy.exe : Error: Unrecognized argument '"-source:"appHostConfig=default'. All arguments must begin with "-".

At C:\xxx\test.ps1:122 char:6

+ &

+ CategoryInfo : NotSpecified: (Error: Unrecogn...begin with "-".:String) [], RemoteException

+ FullyQualifiedErrorId : NativeCommandError

Error count: 1.

The following variations have also failed

#FAIL

$sitename=`'default web site`'

$sitename=`'"default web site"`'

$sitename="`'default web site`'"

$sitename="default web site"

$sitename="'default web site'"

&$msdeploy -verb:dump "-source:appHostConfig=$sitename" -verbose

&$msdeploy -verb:dump -source:appHostConfig="$sitename" -verbose

&$msdeploy -verb:dump -source:appHostConfig='$sitename' -verbose

&$msdeploy -verb:dump -source:appHostConfig=`'$sitename`' -verbose

&$msdeploy -verb:dump -source:appHostConfig=`"$sitename`" -verbose

I'm at a loss. Everyone I work with is at a loss. Seriously this sucks. I loved Powershell. I loved msdeploy. I can't say that I love putting them together. It looks like it may have been easier to focus on the API instead of the cli.

EDIT:

The parameters in the string array suggested by Emperor XLII works well. An alternative solution is presented in the following article: The trials and tribulations of using MSDeploy with PowerShell

function PushToTarget([string]$server, [string]$remotePath, [string]$localPath) {
    cmd.exe /C $("msdeploy.exe -verb:sync -source:contentPath=`"{0}`" -dest:computerName=`"{1}`",contentPath=`"{2}`" -whatif" -f $localPath, $server, $remotePath )
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

何止钟意 2024-09-22 08:30:31

使用 中的技术Keith 的回答 如何要在 powershell 中使用带有空格和引号的参数运行 exe 您链接到的问题,运行 echoargs -verb:dump -source:appHostConfig=$sitename -verbose 给出了以下输出:

Arg 0 is <-verb:dump>
Arg 1 is <-source:appHostConfig=default>
Arg 2 is <web>
Arg 3 is <site>
Arg 4 is <-verbose>

这可以解释msdeploy 发现的 appHostConfig=default 参数无效。

使用 $sitename = "default web site" 运行 echoargs -verb:dump "-source:appHostConfig=$sitename" -verbose 似乎会产生所需的参数:

Arg 0 is <-verb:dump>
Arg 1 is <-source:appHostConfig=default web site>
Arg 2 is <-verbose> 

尽管从您的列表来看,这似乎对您不起作用。

您可以尝试的另一种方法是在数组中构建参数列表,powershell 可以自动转义该列表。例如,这给出了与上面相同的输出:

[string[]]$msdeployArgs = @(
  "-verb:dump",
  "-source:appHostConfig=$sitename",
  "-verbose"
)
echoargs $msdeployArgs

Using the technique from Keith's answer to How to run exe in powershell with parameters with spaces and quotes question you linked to, running echoargs -verb:dump -source:appHostConfig=$sitename -verbose gave me this output:

Arg 0 is <-verb:dump>
Arg 1 is <-source:appHostConfig=default>
Arg 2 is <web>
Arg 3 is <site>
Arg 4 is <-verbose>

This would explain the invalid argument of appHostConfig=default that msdeploy was seeing.

Running echoargs -verb:dump "-source:appHostConfig=$sitename" -verbose, with $sitename = "default web site", appears to result in the desired arguments:

Arg 0 is <-verb:dump>
Arg 1 is <-source:appHostConfig=default web site>
Arg 2 is <-verbose> 

Though from your list, it appears that this did not work for you.

Another method you might try is building up the list of arguments in an array, which powershell can automatically escape. For example, this gives the same output as above:

[string[]]$msdeployArgs = @(
  "-verb:dump",
  "-source:appHostConfig=$sitename",
  "-verbose"
)
echoargs $msdeployArgs
_蜘蛛 2024-09-22 08:30:31

只是添加另一种方式,以防对任何人有帮助:

Invoke-Expression "& '[path to msdeploy]\msdeploy.exe' --% -verb:sync -source:contentPath=`'$source`' -dest:contentPath=`'$dest`'"

“--%”是 powershell 3 的新功能。来自 此处:“您只需添加 --% 序列(两个破折号和命令行中任何位置的百分号),PowerShell 不会尝试解析该行的其余部分。”

Just adding another way in case it is helpful to anyone:

Invoke-Expression "& '[path to msdeploy]\msdeploy.exe' --% -verb:sync -source:contentPath=`'$source`' -dest:contentPath=`'$dest`'"

"--%" is new to powershell 3. From here: "You simply add a the --% sequence (two dashes and a percent sign) anywhere in the command line and PowerShell will not try to parse the remainder of that line."

优雅的叶子 2024-09-22 08:30:31

找到了一个可行的解决方案并且很容易修复。
参考:http://answered.site/all-arguments-must-begin- with--at-cwindowsdtldownloadswebserviceswebservicesidservicepublishedwebsitesidservicedeploymentidservicewsdeployps123/4231580/

$msdeploy = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe"
$msdeployArgs = @(
"-verb:sync",
"-source:iisApp='Default Web Site/HelloWorld'",
"-verbose",
"-dest:archiveDir='c:\temp1'"
)
Start-Process $msdeploy -NoNewWindow -ArgumentList $msdeployArgs

Found a working solution and easy fix.
Reference: http://answered.site/all-arguments-must-begin-with--at-cwindowsdtldownloadswebserviceswebservicesidservicepublishedwebsitesidservicedeploymentidservicewsdeployps123/4231580/

$msdeploy = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe"
$msdeployArgs = @(
"-verb:sync",
"-source:iisApp='Default Web Site/HelloWorld'",
"-verbose",
"-dest:archiveDir='c:\temp1'"
)
Start-Process $msdeploy -NoNewWindow -ArgumentList $msdeployArgs
不美如何 2024-09-22 08:30:31

我们也遇到过类似的问题。我们的修复如下所示,

$path = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe";

$verb = "-verb:sync";

$src = "-source:contentPath=[ESC][ESC][ESC]"c:\aa aa[ESC][ESC][ESC]";

$dest = "-dest:contentPath=[ESC][ESC][ESC]"c:\aa[ESC][ESC][ESC]";

Invoke-Expression "&'$path' $verb $src $dest"; 

其中 ESC - 是转义序列/字符

We had faced the similar kind of issue. Our fix was like below,

$path = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe";

$verb = "-verb:sync";

$src = "-source:contentPath=[ESC][ESC][ESC]"c:\aa aa[ESC][ESC][ESC]";

$dest = "-dest:contentPath=[ESC][ESC][ESC]"c:\aa[ESC][ESC][ESC]";

Invoke-Expression "&'$path' $verb $src $dest"; 

where, ESC - is escape sequence/character

甜心 2024-09-22 08:30:31

我尝试了所有技术,这是唯一对我有用的技术(使用 PowerShell 2)。

cmd.exe /C $("msdeploy.exe -verb:sync -source:package=`"{0}`" -dest:auto,IncludeAcls=`"False`" -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -setParamFile:`"{1}`"" -f $mypackagepath, $myparamfilepath )

I tried every technique under the sun, and this is the only one that worked for me (using PowerShell 2).

cmd.exe /C $("msdeploy.exe -verb:sync -source:package=`"{0}`" -dest:auto,IncludeAcls=`"False`" -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -setParamFile:`"{1}`"" -f $mypackagepath, $myparamfilepath )
把回忆走一遍 2024-09-22 08:30:31

这是从下面的输入得出的另一种方法。

$msdeploy = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe";

$command = "-verb:sync";

$sourcePath = "C:\aa aa\";
$source = $("-source:contentPath=`"{0}`"" -f $sourcePath);

$destPath = "C:\aa"
$destination = $("-dest:contentPath=`"{0}`" -f $destPath);

$msdeploycommand = $("`"{0}`" {1} {2} {3} -verbose" -f $msdeploy, $command, $source, $destination);

cmd.exe /C "`"$msdeploycommand`"";

这迎合了 MSDeploy.exe 位于其包含空格的默认安装文件夹中的情况。因此使用转义字符 (`) 进行换行。

Here is another approach derived from the input below.

$msdeploy = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe";

$command = "-verb:sync";

$sourcePath = "C:\aa aa\";
$source = $("-source:contentPath=`"{0}`"" -f $sourcePath);

$destPath = "C:\aa"
$destination = $("-dest:contentPath=`"{0}`" -f $destPath);

$msdeploycommand = $("`"{0}`" {1} {2} {3} -verbose" -f $msdeploy, $command, $source, $destination);

cmd.exe /C "`"$msdeploycommand`"";

This caters for the MSDeploy.exe being in its default installation folder which contains spaces. Hence the wrapping with the escape character (`).

淑女气质 2024-09-22 08:30:31

我使用了上面答案中的一些想法,并提出了以下更简单的函数来完成这项工作。

请注意,提供 MSDeploy 的完整路径非常重要,因为在构建代理下运行时,它有时无法识别 msdeploy 的路径。

function Deploy([string]$server, [string]$remotePath, [string]$localPath) {
        $msdeploy = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe";
        cmd.exe /C $("`"{3}`" -verb:sync -source:contentPath=`"{0}`" -dest:computerName=`"{1}`",contentPath=`"{2}`" " -f $localPath, $server, $remotePath , $msdeploy )
    }

用法

Deploy $hostName $remotePath $source

I've used some ideas from answers above and came up with the following simpler function to do the thing.

Note that it is important to give the full path to MSDeploy as when running under the build agent it sometimes doesnt recognise the PATH to msdeploy.

function Deploy([string]$server, [string]$remotePath, [string]$localPath) {
        $msdeploy = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe";
        cmd.exe /C $("`"{3}`" -verb:sync -source:contentPath=`"{0}`" -dest:computerName=`"{1}`",contentPath=`"{2}`" " -f $localPath, $server, $remotePath , $msdeploy )
    }

Usage

Deploy $hostName $remotePath $source
少女情怀诗 2024-09-22 08:30:31

以上所有内容对我来说都不起作用,这是有效的解决方案:

# get msdeploy exe
$MSDeploy = ${env:ProgramFiles}, ${env:ProgramFiles(x86)} |
        ForEach-Object {Get-ChildItem -Path $_ -Filter 'MSDeploy.exe' -Recurse} |
        Sort-Object -Property @{Expression={[version]$_.VersionInfo.FileVersion}} -Descending |
        Select-Object -First 1 -ExpandProperty FullName

#build deploy command        
$deplyCmd = """""$MSDeploy"" -verb:sync -dest:iisApp=""Default Web Site"" -enableRule:DoNotDeleteRule -source:iisApp=""$ExtraWebFilesFolder"""    

#execute    
&cmd /c $deplyCmd

All of the above did not work for me, this is the solution that worked:

# get msdeploy exe
$MSDeploy = ${env:ProgramFiles}, ${env:ProgramFiles(x86)} |
        ForEach-Object {Get-ChildItem -Path $_ -Filter 'MSDeploy.exe' -Recurse} |
        Sort-Object -Property @{Expression={[version]$_.VersionInfo.FileVersion}} -Descending |
        Select-Object -First 1 -ExpandProperty FullName

#build deploy command        
$deplyCmd = """""$MSDeploy"" -verb:sync -dest:iisApp=""Default Web Site"" -enableRule:DoNotDeleteRule -source:iisApp=""$ExtraWebFilesFolder"""    

#execute    
&cmd /c $deplyCmd
平定天下 2024-09-22 08:30:31

这个问题肯定已经存在很长时间了,我最近花了一些时间来解决它。结果对我来说是成功的,所以我将其发布在这里,希望它可以帮助以后发现这个问题的其他人。

要解决的第一个问题是删除 msdeploy 路径中的空格。这里有两种方法。一种是持久性的,需要您具有服务器访问权限,另一种是在 PowerShell 脚本上下文中的临时性。两者都可以,但如果您可以选择的话,我更喜欢第一个。

对于第一种方法,创建一个连接点。示例脚本:

new-item -Path "c:\MS-WebDeploy" -ItemType Junction -Value "c:/Program Files (x86)/iis/microsoft web deploy v3"

对于第二种方法,创建一个 PSDrive(本例中为 w)

New-PSDrive -Name "w" -PSProvider FileSystem -Root "C:/Program Files (x86)/iis/microsoft web deploy v3"

我使用下面的三个 PowerShell 变量。出于示例目的,假设所有三个都有空格。

  • $ParamFilePath = "c:\deployment files\parameters.xml"
  • $PackageName = "c:\deployment files\My Website.zip"
  • $WebAppPath = "Default Web Site"

首先,创建一个数组并根据需要构建参数。

#nothing needs to be done with these arguments so we'll start with them
[string[]]$arguments = @("-verb:sync", "-dest:auto", "-disableLink:AppPoolExtension", "-disableLink:ContentExtension", "-disableLink:CertificateExtension", "-allowUntrusted")

#double up on the quotes for these paths after the colon
$arguments += "-setParamFile:""$ParamFilePath"""
$arguments += "-source:package=""$PackageName"""

#must not have spaces with the commma, use single quotes on the name and value here
$arguments += "-setParam:name='IIS Web Application Name',value='$WebAppPath'"

#add your own logic for optional arguments  
$arguments += "-EnableRule:EncryptWebConfig"

现在构建 msdeploy 命令并放置 PowerShell 转义序列以防止 PowerShell 稍后“提供帮助”。使用您通过联结或 PSDrive 创建的路径

$command = "w:\msdeploy.exe" + " --% " + $arguments -join " "

最后,将该命令作为脚本块执行。

$sb = $ExecutionContext.InvokeCommand.NewScriptBlock($command) 
& $sb

我已将这段代码和更多代码封装到一个脚本中,如下所示。

.\Run-WebDeploy -WebAppPath "Default Web Site" -PackageName "c:\deployment files\My Website.zip"  -ParamFilePath "c:\deployment files\parameters.xml"  -EncryptWebConfig

一般来说,去掉路径/名称中的空格可以给自己带来很多帮助。有时,这是无法做到的,但这应该可以帮助您渡过难关。

This problem has certainly been around for a long time and I spent some time battling it recently. The result has been successful for me so I'll post it here in hopes that it can help others who find this question in the future.

The first problem to resolve is getting rid of the spaces in the msdeploy path. There are two approaches here. One is persistent and requires you to have server access, the other is temporary in the context of your PowerShell script. Either will work but I'd prefer the first if it's an option for you.

For the first approach, create a junction point. Example script:

new-item -Path "c:\MS-WebDeploy" -ItemType Junction -Value "c:/Program Files (x86)/iis/microsoft web deploy v3"

For the second approach, create a PSDrive (w in this example)

New-PSDrive -Name "w" -PSProvider FileSystem -Root "C:/Program Files (x86)/iis/microsoft web deploy v3"

I'm using three PowerShell variables below. For example purposes, pretend that all three have spaces.

  • $ParamFilePath = "c:\deployment files\parameters.xml"
  • $PackageName = "c:\deployment files\My Website.zip"
  • $WebAppPath = "Default Web Site"

First, create an array and build up your arguments as needed.

#nothing needs to be done with these arguments so we'll start with them
[string[]]$arguments = @("-verb:sync", "-dest:auto", "-disableLink:AppPoolExtension", "-disableLink:ContentExtension", "-disableLink:CertificateExtension", "-allowUntrusted")

#double up on the quotes for these paths after the colon
$arguments += "-setParamFile:""$ParamFilePath"""
$arguments += "-source:package=""$PackageName"""

#must not have spaces with the commma, use single quotes on the name and value here
$arguments += "-setParam:name='IIS Web Application Name',value='$WebAppPath'"

#add your own logic for optional arguments  
$arguments += "-EnableRule:EncryptWebConfig"

Now build the msdeploy command and put the PowerShell escape sequence to prevent PowerShell from "helping" later. Use the path you created with the junction or the PSDrive

$command = "w:\msdeploy.exe" + " --% " + $arguments -join " "

Finally, execute that command as a script block.

$sb = $ExecutionContext.InvokeCommand.NewScriptBlock($command) 
& $sb

I've wrapped this and a bit more code into a script which is called like this.

.\Run-WebDeploy -WebAppPath "Default Web Site" -PackageName "c:\deployment files\My Website.zip"  -ParamFilePath "c:\deployment files\parameters.xml"  -EncryptWebConfig

In general, you can help yourself a lot by getting rid of the spaces in your paths/names. Sometimes, that can't be done and this should get you through.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文