What is up with this PowerShell command line quoting/escaping?
I finally found out how to do this. Here is a sample script:
$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'
$command = "& `$msdeploy --% -verb:sync -source:contentPath=""$src"" -dest:contentPath=""$dest"""
$sb = $ExecutionContext.InvokeCommand.NewScriptBlock($command)
& $sb
This is a notorious issue. The ticket “Executing commands which require quotes and variables is practically impossible” is the most voted bug: https://connect.microsoft.com/PowerShell/Feedback
You can find there a few workarounds as well. But I would recommend you to compose all the parameters as an array and use the &
operator to invoke a native command with this array. See the answers and examples:
Running an EXE file using PowerShell from a directory with spaces in it
and
Executing a Command stored in a Variable from Powershell
I did not work with msdeploy.exe
and cannot provide some demo code for your case. But I applied this approach to many other tricky native commands well enough. Please, try it and let us know the results.
P.S. Technically this is not exactly an answer to your questions but I assume you are still looking for a practical way of doing this, so it still might be helpful.
One of the areas at fault here is the inability of PowerShell to cope with the translation of the whitespace between "Program Files" expressed in the cmd-based msdeploy.
This is an extremely basic solution and leverages antiquated DOS limitations, but the following non-whitespace references can be used in their stead:
\Program Files\ ... \Progra~1\
\Program Files (x86)\ ... \Progra~2\
It's lame, but it works.
You can also create a function that calls cmd and executes your command. This example also assumes what you're trying to call (msdeploy, etc.) is in the path.
function PushToTarget() {
cmd.exe /C $("msdeploy.exe -verb:sync -source:apphostconfig=yourwebapp-dev -dest:archivedir=d:\backup")
}