12

I obviously don't know what I'm doing.

I have finally got this PowerShell command to work. But I can't figure out why it works.

My concern is the final "" characters:

    &"C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" `
    -verb:sync `
    -source:contentPath="$build_directory\deploy" `
    -dest:contentPath="$server_temp_directory,computerName=$server,username=$server_username,password=$server_password" `
    -verbose `
    -postSync=runCommand="powershell -NoLogo -NoProfile -Command $server_temp_directory\remotetasks.ps1 Deploy""

Why do I need double double-quotes?

My IDE (PowerGUI) says the line is not ended correctly, but it is the only way I can make the command run as wanted.

What is it, that I - and the IDE - don't know about quoting in PowerShell?


A little output from echoargs:

If I run:

echoargs -postSync=runCommand="powershell -NoLogo -NoProfile -Command $server_temp_directory\remotetasks.ps1 Deploy""

I get:

Arg 0 is <-postSync=runCommand=powershell -NoLogo -NoProfile -Command \remotetasks.ps1 Deploy>

If I run without the double double-quotes, I get:

Arg 0 is <-postSync=runCommand=powershell>
Arg 1 is <-NoLogo>
Arg 2 is <-NoProfile>
Arg 3 is <-Command>
Arg 4 is <\remotetasks.ps1>
Arg 5 is <Deploy>

Another thing to notice is that the above command does only work if it uses = instead of : in the last argument.

This won't work:

-postSync:runCommand="powershell -NoLogo -NoProfile -Command $server_temp_directory\remotetasks.ps1 Deploy""

I have tried the array solution like this:

$arguments = @("-verb:sync",
               "-source:contentPath=$build_directory\deploy",
               "-dest:contentPath=$server_temp_directory,computerName=$server,username=$server_username,password=$server_password",
               "-verbose",
               "-postSyncOnSuccess:runCommand=powershell -Command $server_temp_directory\remotetasks.ps1 Deploy")
&"C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" $arguments

I still get the same error:

Error: Unrecognized argument '"-postSyncOnSuccess:runCommand=powershell -Command c:\temp\kslog\remotetasks.ps1 Deploy"'. All arguments must begin with "-".

Am I doing some new thing wrong here?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
asgerhallas
  • 16,890
  • 6
  • 50
  • 68

3 Answers3

11

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.

Community
  • 1
  • 1
Roman Kuzmin
  • 40,627
  • 11
  • 95
  • 117
  • Thank you for the answer! I'm away from the code this weekend, but I will try out your suggestions when I get back monday. You're right, that this is technically not an answer to why the double double-qoutes works... but if it is a bug, and not by design, then it might not be worth getting a deeper understanding of anyway. I'll return shortly. – asgerhallas Oct 09 '10 at 07:40
  • So. I have tried all sorts of combinations of using an array for the parameters. Nothing seems to work. Do you have an idea why? – asgerhallas Oct 12 '10 at 12:34
  • I do not use msdeploy.exe and cannot try it myself. Can you now try the last argument with two extra escaped quotation marks: "-postSyncOnSuccess:runCommand="powershell -Command $server_temp_directory\remotetasks.ps1 Deploy"" ( is for backticks, to avoid SO formatting) – Roman Kuzmin Oct 12 '10 at 14:19
  • Thank you for the suggestion! Unfortunately it does not make a difference. I still get the same error message. Well, in fact it does make a tiny difference: When doing it with the escaped qoute marks the echoargs command returns 8 arguments, when doing it without it actually return only 5. None of them work when executed, but the difference is somewhat strage... See http://gist.github.com/623756 – asgerhallas Oct 13 '10 at 09:45
  • Weird... I am about to give up. BTW, just in case, I have taken a look at MSDN for msdeploy.exe syntax. There is no `postSyncOnSuccess` there, I can see only `postSync`. Can this be a reason? That would explain the error message about “Unrecognized argument”. http://technet.microsoft.com/en-us/library/dd569089(WS.10).aspx – Roman Kuzmin Oct 13 '10 at 11:22
  • Thank you very much for your patience! It still doesn't work, even if I use only the documented syntax (the other one is actually available too). But I give up now too :) – asgerhallas Oct 13 '10 at 13:10
  • 1
    Here we are in 2013 and powershell and msdeploy still cannot cope. I had the same problem and after much hair pulling ended up calling msdeploy.exe from a batch file (which kinda defeats the purpose of powershell). I wish MS would address this. – Mike Cheel Jul 09 '13 at 14:42
3

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mike Cheel
  • 12,626
  • 10
  • 72
  • 101
1

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")
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
efisher
  • 223
  • 4
  • 12