25

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

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

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

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

这个?

$sitename="default web site"
&$msdeploy -verb:dump -source:appHostConfig=$sitename -verbose
==FAIL 并出现以下错误
msdeploy.exe:错误:无法识别的参数 '"-source:"appHostConfig=default'。所有参数必须以“-”开头。
在 C:\xxx\test.ps1:122 char:6
+ &
+ CategoryInfo : NotSpecified: (Error: Unrecogn...begin with "-".:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
错误计数:1。

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

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

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

编辑:

Emperor XLII 建议的字符串数组中的参数效果很好。以下文章中介绍了另一种解决方案:将 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 )
}
4

9 回答 9

14

使用Keith对How to run exe in powershell 的回答中的技术,使用您链接到的带有空格和引号的问题的参数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>

这将解释所看到的无效appHostConfig=default论点msdeploy

Running echoargs -verb:dump "-source:appHostConfig=$sitename" -verbose, with $sitename = "default web site",似乎会产生所需的参数:

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
于 2010-08-17T13:41:46.583 回答
10

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

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

“--%”是 powershell 3 的新功能。从这里开始:“您只需在命令行的任意位置添加 --% 序列(两个破折号和一个百分号),PowerShell 将不会尝试解析该行的其余部分。 "

于 2015-06-19T17:47:57.003 回答
7

找到了一个可行的解决方案并轻松修复。参考: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
于 2015-12-10T07:28:58.157 回答
6

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

$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- 是转义序列/字符

于 2012-10-10T06:12:56.947 回答
3

我在阳光下尝试了每一种技术,这是唯一对我有用的技术(使用 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 )
于 2014-02-22T17:16:23.487 回答
1

这是从下面的输入派生的另一种方法。

$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 在其包含空格的默认安装文件夹中。因此使用转义字符 (`) 进行换行。

于 2014-08-07T23:51:38.623 回答
0

我从上面的答案中使用了一些想法,并提出了以下更简单的功能来做这件事。

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

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
于 2016-10-03T23:35:55.637 回答
0

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

# 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
于 2017-09-29T11:36:08.210 回答
0

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

要解决的第一个问题是去掉 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:\部署文件\parameters.xml"
  • $PackageName = "c:\部署文件\我的网站.zip"
  • $WebAppPath = "默认网站"

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

#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

通常,您可以通过删除路径/名称中的空格来帮助自己。有时,这是无法做到的,这应该可以让您通过。

于 2019-11-30T23:51:16.473 回答