开发者

How do you call msdeploy from powershell when the parameters have spaces?

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

+ &

+ Categ开发者_Python百科oryInfo : 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 )
}


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


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."


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


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


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 )


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 (`).


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


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜