Calling msdeploy.exe from powershell with variables that contain spaces

I (and apparently many people on the internet) been struggling with calling msdeploy.exe with variables that contain spaces. Here is an example:

$src=‘c:\sandbox\Test Folder\A’
$dest=‘c:\sandbox\Test Folder\B’
$msdeploy=Get-Command ‘C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe’
& $msdeploy -verb:sync -source:contentPath=“‘$src’” -dest:contentPath=“‘$dest’”

I can call it when there are no spaces. I can call it with literal values.

Can anyone tell me how to accomplish calling msdeploy.exe with variables that contain spaces for the parameters? (Warning: everyone else has gone bald pulling out their hair)

So, the problem is probably in the way PowerShell is parsing stuff before passing it off to Cmd.exe. One option would be to dynamically write out a .BAT file and then call it. That’d help get PSH out of the loop. On PSHv3, you might also try the --% trick. Put that after Msdeploy and PowerShell stops parsing from there. Sadly, that means it stops parsing from there - meaning the variables get treated as literals. Nevermind. But maybe the batch file thing.

Have you guys looked into PSCX’s little echoargs tool, to see what PowerShell is actually spewing to Cmd.exe?

I can do it with a batch file. I was wondering if it is possible to do it straight out of powershell. I’ve used the echoargs tool but still have never been able to get it to work. As much as I like powershell (and I really do) am a little disappointed that so far I have had to resort to use the ‘old stuff’ (i.e. cmd) to do this.

You should be able to make this work using PowerShell. Here’s what I would do:

  1. Work out the command if you were to enter everything on one line without variables.
  2. Take your equivalent command with variables and expand it to see if it contains what you actually think it contains.

For example, I took your above code and did this with it:

$src=’c:\sandbox\Test Folder\A’
$dest=’c:\sandbox\Test Folder\B’
$msdeploy=Get-Command ‘C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe’
@"
& $msdeploy -verb:sync -source:contentPath=“‘$src’” -dest:contentPath=“‘$dest’”
"@

This doesn’t invoke anything. Instead, it spits out a string showing me what PowerShell would see if it were to expand the variables. This isn’t a perfect test, but it can be quite illuminating.

Also, when you invoke it when there are spaces, what errors are you getting? Knowing those errors would be helpful in identifying which portion of the command is having issues.

Oh, and without seeing the results, since I can see what that command looks like with the variables expanded, my guess would be that you don’t want to use single-quotes inside of your double-quotes surrounding $src and $dest.

@Poshoholic

I can get it to work if I hard code it with literal values. I’ve tried all sorts of variations (including your suggestions) and could only get it to work by putting the command in a batch file. I’ve been trying to figure this out for a while now and posted about it in other places. No one has been able to figure it out.

To answer your question when I do it without the single quotes I get:

msdeploy.exe : Error: Unrecognized argument ‘"-source:"contentPath=c:\sandbox\Test’.
All arguments must begin with “-”.
At C:\Sandbox\msdeploy.ps1:6 char:1

  • & $msdeploy -verb:sync -source:contentPath=“$src” -dest:contentPath=“$dest”
  •   + CategoryInfo          : NotSpecified: (Error: Unrecogn...begin with "-".:Strin 
     g) [], RemoteException
      + FullyQualifiedErrorId : NativeCommandError
    
    

Error count: 1.

If I use the single quotes like I originally posted I get:

msdeploy.exe : Error: Unrecognized argument ‘“-source:“contentPath=‘c:\sandbox\Test Folder\A’””’. All arguments must begin with
“-”.
At C:\Sandbox\msdeploy.ps1:6 char:1

  • & $msdeploy -verb:sync -source:contentPath=“‘$src’” -dest:contentPath=“‘$dest’”
  •   + CategoryInfo          : NotSpecified: (Error: Unrecogn...begin with "-".:String) [], RemoteException
      + FullyQualifiedErrorId : NativeCommandError
    
    

Error count: 1.

Ok, have you tried Don’s suggestion, using -%?

For example:

& $msdeploy -% -verb…

The -% tells PowerShell to stop processing the remaining arguments like they are PowerShell parameters and instead treat them as simple text arguments for the command.

Oh, and I get that you want to use variables, so you can work around that, sort of.

$command = “& `$msdeploy -% -verb:sync -source:contentPath=”“‘$src’”" -dest:contentPath=“”‘$dest’“”"
$sb = $ExecutionContext.InvokeCommand.NewScriptBlock($command)
& $sb

By defining the command in a string with variables that you want to expand, and then creating the script block with the -% so that it doesn’t parse those string arguments, that may be the trick you were looking for.

@Poshoholic

I had to adjust the -% to be --% and I had to remove the single quotes completely because they were being included. And then…it…worked!

Thanks so much!

One last question please. What is the tick mark doing right before $msdeploy?

Excellent, thanks for letting me know! :slight_smile: