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

Iis 当参数有空格时,如何从powershell调用msdeploy?,iis,powershell,msdeploy,Iis,Powershell,Msdeploy,我尝试从powershell脚本将参数中的空格发送到msdeploy时遇到问题 有许多其他相关的文章,但没有一篇能够解决这个问题。 类似的SO问题不起作用: PowerShell错误: 另一个不起作用的SO问题: 最简单的例子是,当我把它弄得更复杂时,它成功了,然后又失败了,那就是转储默认的web站点 $msdeploy=“C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe” &$msdeploy-verb:dump-source:a

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

有许多其他相关的文章,但没有一篇能够解决这个问题。

类似的SO问题不起作用:
PowerShell错误:
另一个不起作用的SO问题:

最简单的例子是,当我把它弄得更复杂时,它成功了,然后又失败了,那就是转储默认的web站点

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

这个

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

以下变体也失败了
#失败
$sitename=`'默认网站`'
$sitename=``默认网站`
$sitename=“`'默认网站`”
$sitename=“默认网站”
$sitename=“‘默认网站’”

&$msdeploy-verb:dump“-source:appHostConfig=$sitename”-详细
&$msdeploy-verb:dump-source:appHostConfig=“$sitename”-详细
&$msdeploy-verb:dump-source:appHostConfig='$sitename'-verbose
&$msdeploy-verb:dump-source:appHostConfig=`$sitename`'-verbose
&$msdeploy-verb:dump-source:appHostConfig=`“$sitename`”-详细

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

编辑: 皇帝XLII建议的字符串数组中的参数运行良好。下一篇文章介绍了另一种解决方案:

使用您链接到的问题的技术,运行
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>
虽然从您的列表中可以看出,这似乎不适合您

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

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

我们曾经面临过类似的问题。我们的解决方案如下所示

$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-is escape sequence/character

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


下面是从下面的输入导出的另一种方法

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

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

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

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

找到了一个有效的解决方案并轻松修复。 参考:


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

请注意,提供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

以上所有这些都不适用于我,这是有效的解决方案:

# 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

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

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

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

new-item -Path "c:\MS-WebDeploy" -ItemType Junction -Value "c:/Program Files (x86)/iis/microsoft web deploy v3"
对于第二种方法,创建一个PSDrive(本例中为w)

我在下面使用了三个PowerShell变量。例如,假设所有三个都有空格

  • $ParamFilePath=“c:\deployment files\parameters.xml”
  • $PackageName=“c:\deployment files\My Website.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

一般来说,您可以通过去掉路径/名称中的空格来帮助自己。有时候,这是做不到的,这应该会帮你度过难关。

在你发布解决方案后,我还被指向这篇文章:谢谢你的帮助。请向上投票上面列出的PowerShell参数错误/缺陷。对于那些可能错过它的人(我花了一点时间找到了提到的链接),这里是PowerShell connect错误:与其做疯狂的事情来突出显示您的代码,不如使用4个空格(检查我的编辑)。这是唯一一件最终对我有效的事情。但我认为您在src和des$src=“-source:contentPath=[ESC][ESC][ESC][ESC]”的末尾缺少一个引号,c:\aa aa[ESC][ESC][ESC]”;我还要补充一点,powershell的[Esc]字符是`字符。不是一个单一的报价,而是向后的口音(通常与键盘上的倾斜配对)或考虑使用。
New-PSDrive -Name "w" -PSProvider FileSystem -Root "C:/Program Files (x86)/iis/microsoft web deploy v3"
#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"
$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