Как избежать кавычек в команде msdeploy post sync, которая выполняет сценарий powershell? - PullRequest
3 голосов
/ 24 мая 2019

Я пытаюсь настроить задачу Cake, которая будет использовать MsDeploy для синхронизации сценария powershell с удаленным сервером, а затем выполнить этот сценарий в качестве команды после синхронизации.

Проблема, с которой я сталкиваюсь, заключается в поискекомбинация кавычек и экранировок в файле тортов, позволяющая команде полностью перейти на powershell с правильно указанным путем к файлу, чтобы powershell мог найти скрипт;путь содержит пробелы.

Это кажется настолько сложным из-за цепочки выполнения, что эта команда проходит во время выполнения.Во-первых, потому что это написано на C #, строка должна быть дословной (@"command here") или экранировать все внутренние двойные кавычки с помощью \.

Next Cake выполняет несколько операций с аргументами, хотя ни одна из них не показаласьвоздействовать на такие вещи, как цитирование и экранирование до тех пор, пока он фактически не дойдет до выполнения, после чего он использует статический метод C # Process.Start() для запуска исполняемого файла MsDeploy.В моем чтении было предложено, чтобы этот метод запуска команды требовал правильного экранирования трех двойных кавычек, хотя это не совпало с тем, что я видел, когда пытался.

Затем один раз на удаленной машине MsDeployиспользует CMD.exe для выполнения команды, которая, в частности, не поддерживает одинарные кавычки, поэтому двойные кавычки либо нужно экранировать, используя \" или "".

Ближайшее, что я получил, выглядит так:

Task("InitializeIISApplication")
    .IsDependentOn("InjectVariables") 
    .Does(() => {
        MsDeploy(new MsDeploySettings
        {
            Verb = Operation.Sync,
            RetryAttempts = 3,
            RetryInterval = 10000,
            Source = new FilePathProvider
            {
                Direction = Direction.source,
                Path = MakeAbsolute(File(@".\MyPowershell.ps1")).ToString()        
            },
            Destination = new FilePathProvider
            {
                Direction = Direction.dest,
                Path = File(deployParameters.ApplicationDestinationPath + @"\MyPowershell.ps1").ToString(),
                Username = deployParameters.MsDeployUserName,
                Password = deployParameters.MsDeployUserPassword,
                WebManagementService = deployParameters.DeploymentTargetUrl
            },
            AllowUntrusted = true,
            EnableRules = new List<string> {
                "DoNotDeleteRule"
            },
            PostSyncCommand = new CommandProvider {
                AppendQuotesToPath = false,
                Direction = Direction.dest,
                Path = $"powershell -file '{deployParameters.ApplicationDestinationPath}\\MyPowershell.ps1' ",
            }
        });

        MsDeploy(new MsDeploySettings
        {
            Verb = Operation.Delete,
            Destination = new FilePathProvider
            {
                Direction = Direction.dest,
                Path = File(deployParameters.ApplicationDestinationPath + "\MyPowershell.ps1").ToString(),
                Username = deployParameters.MsDeployUserName,
                Password = deployParameters.MsDeployUserPassword,
                WebManagementService = deployParameters.DeploymentTargetUrl
            },
            AllowUntrusted = true
        });
    });

Зависимость задачи - это просто установка объекта deployParameters.

, который при включенном многогранности диагностики Cake выдает в журналы следующую команду (новые строки добавлены для ясности):

"C:/Program Files/IIS/Microsoft Web Deploy V3/msdeploy.exe"  
-verb:sync   
-source:filePath="Y:/PathToBuildArtifact/Deploy/MyPowershell.ps1"
-dest:filePath="C:/Application - With Spaces/MyPowershell.ps1",wmsvc="https://deploy-server/msdeploy.axd",userName=msdeployuser,password=********
-enableRule:DoNotDeleteRule
-retryAttempts:3
-retryInterval:10000
-allowUntrusted
-postSync:runCommand="powershell -file 'C:\Application - With Spaces\MyPowershell.ps1' "

Затем завершается с ошибкой:

Предупреждение: Обработка -File '' C: / Application 'завершилась неудачно: формат данного пути не поддерживается.Укажите допустимый путь для параметра -File.

Любой вариант, в котором я пытался использовать двойные кавычки внутри команды postSync, вместо этого приводит к этой ошибке:

Ошибка: не распознанааргумент '-'.

Если это имеет значение, это делается на сервере Bamboo CI.

Ответы [ 2 ]

2 голосов
/ 27 мая 2019

Использование параметра CLI PowerShell -File требует использования " в качестве символа только поддерживаемой кавычки.

(В отличие от этого, использование -Command предписывает PowerShell обрабатыватьостальная часть командной строки, как если бы это был исходный код PowerShell , в этом случае ' * распознается как символ кавычки, для строк с литеральным содержимым [1] ).

Поскольку ваша командная строка PowerShell становится аргументом в двойных кавычках для другой команды , которая в конечном итоге передается cmd.exe, , вы должны дополнительно , \ -экранирование символов ".

Следовательно, следующее должно работать [ update : , но не работает - см. Комментарии]:

Path = $"powershell -file \\\"{deployParameters.ApplicationDestinationPath}\\MyPowershell.ps1\\\"",

Или, используя дословную строку:

Path = $@"powershell -file \""{deployParameters.ApplicationDestinationPath}\MyPowershell.ps1\""",

[1] -File требуется двойной -квотированный аргумент файла сценария, а все остальные аргументы обрабатываются как литералы .
В отличие от -Command (то есть подразумевается опция в Windows PowerShell , тогда как в PowerShell Core она теперь -File) объединяет все оставшиеся аргументы , а обрабатывает результат как код PowerShell, что означает, что одиночные аргументы в кавычках также поддерживаются, с индивидуально двойными кавычками аргументы, имеющие свои кавычки раздетые передконкатенация.

2 голосов
/ 25 мая 2019

Оказывается, это был аргумент -file, который вызывал странное поведение при разборе. При вызове powershell -help в командной строке отображается следующий фрагмент:

Запускает указанный сценарий в локальной области («с точечным источником»), так что функции и переменные, которые создает скрипт, доступны в текущая сессия. Введите путь к файлу скрипта и любые параметры. Файл должен быть последним параметром в команде, потому что все символы вводится после интерпретации имени параметра File в качестве пути к файлу сценария, за которым следуют параметры сценария.

Что намекает на то, что там есть какая-то особая логика.

Таким образом, вместо этого я попытался выполнить файл, используя оператор вызова (&), и после пары разных попыток процитировать я получил следующую команду после синхронизации, которая успешно прошла:

PostSyncCommand = new CommandProvider {
                Direction = Direction.dest,
                Path = $"powershell \"\"& \"\"\"\"{deployParameters.ApplicationDestinationPath}\\MyPowershell.ps1\"\"\"\" \"\"",
            }

Обратите внимание, что все, что после powershell содержится в двух двойных кавычках, первое действует как экранирование для вызова msdeploy, а строки внутри должны иметь четыре кавычки: первое и третье для экранирования второго и четвертого для вызова msdeploy и второй затем избегает четвертого для последнего вызова powershell.

...