Что происходит с этой командной строки PowerShell, цитирующей/экранирующей?

Я, очевидно, не знаю, что я делаю.

Наконец-то я получил команду PowerShell для работы. Но я не могу понять, почему это работает.

Моя забота - это окончательные "" символы:

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

Зачем мне нужны двойные кавычки?

Моя IDE (PowerGUI) говорит, что строка не закончилась правильно, но это единственный способ заставить команду запускаться по мере необходимости.

Что это такое, что я - и IDE - не знаю о Qouting в PowerShell?


Небольшой выход из эхолота:

Если я запустил:

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

Я получаю:

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

Если я запускаю без двойных кавычек, я получаю:

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>

Еще одна вещь, которую следует заметить, заключается в том, что указанная выше команда работает, только если она использует = вместо: в последнем аргументе.

Это не сработает:

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

ИЗМЕНИТЬ

Теперь я попробовал решение массива следующим образом:

$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

Я все равно получаю ту же ошибку:

Ошибка: непризнанный аргумент ' "-postSyncOnSuccess: runCommand = powershell -Command c:\temp\kslog\remotetasks.ps1 Развернуть". Все аргументы должны начинаться с "-".

Я делаю что-то новое здесь неправильно?

Ответ 1

Это печально известная проблема. Билет "Выполнение команд, для которых требуются кавычки и переменные практически невозможно", является самой голосовой ошибкой: https://connect.microsoft.com/PowerShell/Feedback

Вы можете найти там несколько обходных решений. Но я бы рекомендовал вам составить все параметры в виде массива и использовать оператор & для вызова собственной команды с этим массивом. См. Ответы и примеры: Запуск EXE файла с помощью PowerShell из каталога с пробелами в нем а также Выполнение команды, хранящейся в переменной из Powershell

Я не работал с msdeploy.exe и не могу предоставить демо-код для вашего дела. Но я применил этот подход ко многим другим сложным родным командам достаточно хорошо. Пожалуйста, попробуйте и сообщите нам о результатах.

P.S. Технически это не совсем ответ на ваши вопросы, но я предполагаю, что вы все еще ищете практический способ сделать это, поэтому он может быть полезен.

Ответ 2

Наконец-то я узнал, как это сделать. Вот пример 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

Ответ 3

Одна из проблемных областей здесь - неспособность PowerShell справиться с переводом пробелов между "программными файлами", выраженными в msdploy на основе cmd.

Это чрезвычайно базовое решение и использует устаревшие ограничения DOS, но вместо них могут использоваться следующие ссылки без пробелов:

\Program Files\ ... \Progra~1\
\Program Files (x86)\ ... \Progra~2\

Он хромой, но он работает.

Вы также можете создать функцию, которая вызывает cmd и выполняет вашу команду. В этом примере также предполагается, что вы пытаетесь вызвать (msdeploy и т.д.) В пути.

function PushToTarget() {
     cmd.exe /C $("msdeploy.exe -verb:sync -source:apphostconfig=yourwebapp-dev -dest:archivedir=d:\backup")
}