【问题标题】:How do you call msdeploy from powershell when the parameters have spaces?当参数有空格时,如何从 powershell 调用 msdeploy?
【发布时间】:2011-03-30 19:21:13
【问题描述】:

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

还有许多其他相关文章,但没有一篇能解决问题。
Problems Using Power Shell And MSDeploy.
类似的 SO 问题不起作用:How to run exe in powershell with parameters with spaces and quotes
PowerShell 错误: Executing commands which require quotes and variables is practically impossible
另一个不起作用的 SO 问题:Passing parameters in 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
==FAIL 出现以下错误
msdeploy.exe:错误:无法识别的参数 '"-source:"appHostConfig=default'。所有参数必须以“-”开头。
在 C:\xxx\test.ps1:122 char:6
+ &
+ CategoryInfo : NotSpecified: (错误: Unrecogn...begin with "-".:String) [], 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 可能更容易。

编辑:

Emperor XLII 建议的字符串数组中的参数效果很好。以下文章中介绍了另一种解决方案: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 Deploy PowerShell Cmdlets
  • Web Deploy PowerShell Cmdlet 在 2010 年不可用。团队提供的唯一选择是使用 PowerShell 直接访问 .Net API。 blogs.iis.net/jamescoo/archive/2009/09/09/… 我认为直到 v3 才添加 cmd-let。
  • 您编辑的文章有一个新网址:trycatchfail.com/2010/02/01/…
  • @JulianM Web Deploy Powershell Cmdlet 的文档很糟糕,通过搜索,显然整个行业都没有使用。不值得花时间去弄清楚。
  • 升级到最新的 Powershell 版本可能会有所帮助。在this answer中查看我的示例代码

标签: iis powershell msdeploy


【解决方案1】:

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

要解决的第一个问题是去掉 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:\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

一般来说,去掉路径/名称中的空格对您有很大帮助。有时,这是无法做到的,这应该可以帮助您度过难关。

【讨论】:

    【解决方案2】:

    以上所有方法都不适合我,这是有效的解决方案:

    # 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
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        找到一个可行的解决方案并轻松修复。 参考: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
        

        【讨论】:

        • 这对我有用。注意Start-Process 没有设置$LASTEXITCODE。如果您需要检查退出代码,请使用-Wait-PassThru 开关。然后Start-Process 返回一个具有ExitCode 属性的进程对象。
        【解决方案5】:

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

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

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

        【讨论】:

        • 迄今为止我见过的最简单的。让我在一分钟内去。
        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

          我在阳光下尝试了所有技术,这是唯一对我有用的技术(使用 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 )
          

          【讨论】:

            【解决方案8】:

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

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

            【讨论】:

            • 不要做疯狂的事情来突出你的代码,而是使用 4 个空格(检查我的编辑)。
            • 这是唯一对我有用的东西。但我认为您在 src 和 des $src = "-source:contentPath=[ESC][ESC][ESC]"c:\aa aa[ESC][ESC][ESC]"" 末尾缺少引号;
            • 我还要补充一点,powershell 的 [Esc] 字符是 ` 字符。不是单引号,而是后向重音(通常与键盘上的波浪号配对)
            【解决方案9】:

            使用您链接到的问题从Keith's answerHow to run exe in powershell with parameters with spaces and quotes 的技术,运行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 的无效参数。

            运行echoargs -verb:dump "-source:appHostConfig=$sitename" -verbose$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
            

            【讨论】:

            猜你喜欢
            • 2014-09-28
            • 2021-05-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-04-30
            • 2014-06-02
            • 2020-06-18
            相关资源
            最近更新 更多