Search code examples
powershellcmdmsdeploy

MSDEPLOY powershell script parameters does not work


I am trying to deploy a site (basically a zip file) from my machine to a remote machine. I was testing the same before I implement the actual remote deployment and I was working to the msdeploy command line code using powershell.

Later I will configure this code in C# language and execute it that will automate the deployment.

Right now , I am facing the error called

$msdeploy = "C:\\Program Files\\IIS\\Microsoft Web Deploy V3\\msdeploy.exe"
            $package = "C:\Deploy\Test\Test.zip"
            $compname = "test_vm02"
            $appname = "Default Web Site/Test"
            $appvalue = "Test\"
            $md = $("`"{0}`" -verb:sync -source:package=`"{1}`" -dest=auto,ComputerName=`"{2}`" -setParam=name=`"{3}`",value=`"{4}`" -allowUntrusted" -f $msdeploy, $package, $compname, $appname, $appvalue)
        cmd.exe /C $md

This gives error saying that source does not support the parameter 'Default Web Site/Test'.Must be one of ()

I also replaced the default web site to IIS Web Application Name which in this case also did not work and threw the same error.

Any help is much appreciated!!


Solution

  • PowerShell's handling of quotes in arguments passed to external programs is fundamentally broken, but things get more complicated if there's another level of quoting involved, as in your indirect call to msdeploy.exe via cmd.exe.

    There is usually no reason to call external programs via cmd /c; instead, call them directly from PowerShell, which, if the program name is quoted or given via a variable, requires prepending the command line with &, the call operator:

    Note: The line-ending ` chars. are line continuations, used for readability only; ignore the broken syntax highlighting.

    $package = 'C:\Deploy\Test\Test.zip'
    $compname = 'test_vm02'
    $appname = 'Default Web Site/Test'
    # !! If a value ends in '\' you must *double* the '\' if the value
    # !! ends up just before a " in the ultimate command line.
    $appvalue = 'Test\\'
    
    & "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" `
      -verb:sync `
      -source:package=`"$package`" `
      `-dest=auto,ComputerName=`"$compname`" `
      `-setParam=name=`"$appname`",value=`"$appValue`" `
      -allowUntrusted
    

    Note the need to `-escape the - before the -dest and -setParam options, which is a workaround for the bug described in this GitHub issue.

    Leaving the parameter names (e.g. -source:package) otherwise unquoted and enclosing their arguments in explicit, embedded quotes (`") ensures that the whole token is passed through looking something like -source:package="C:\Deploy\Test\Test.zip", which some programs, notably msiexec.exe and possibly also msdeploy.exe, require.

    Caveat: If PowerShell's broken (re)quoting of arguments passed to external programs (see this answer) should ever get fixed (see this GitHub issue), this technique will break.

    If you just used -source:package=$package and the value of $package contained embedded spaces, PowerShell would double-quote the whole token behind the scenes and pass something like
    "-source:package=C:\Deploy 1\Test\Test.zip"

    Programs such as msiexec.exe and msdeploy.exe should recognize this quoting style too, but unfortunately don't.