Как правильно объединить строку в встроенном скрипте Powershell в Azure DevOps? - PullRequest
1 голос
/ 22 января 2020

Я пытаюсь объединить строку для создания пути:

$SourceDirectoryPath = $(System.DefaultWorkingDirectory) + "/solution/project/bin/Debug"
$TargetFilePath = $(System.DefaultWorkingDirectory) + "/solution/project/bin/Debug/" + $(Release.ReleaseName) +$(Release.EnvironmentName)

, но вместо объединения строки я получаю ошибку для второй строки:

d: \ a \ r1 \ a: термин «d: \ a \ r1 \ a» не распознается как имя командлета, функции, файла сценария или работоспособной программы. Проверьте правильность написания имени или, если путь был включен, проверьте правильность пути и повторите попытку. В D: \ a_temp \ 9de874c9-3acd-4a19-a4dd-763074d38e40.ps1: 2 char: 25

, где, очевидно, d:\a\r1\a является $(System.DefaultWorkingDirectory), но почему он выдает эту ошибку, а не просто конкатенация строки?

Ответы [ 3 ]

2 голосов
/ 22 января 2020

Примечание : $(System.DefaultWorkingDirectory) в вопросе: Azure Макрос конвейера (переменный), расширенный Azure перед PowerShell видит команду - ее не следует путать с собственным оператором подвыражения PowerShell , $(...).


Ответ Шайки Абрамчика обеспечивает эффективное решение, но позвольте мне предоставить некоторую справочную информацию :

Расширение (замена) значения , которое Azure выполняет с помощью макроса $(...), работает как препроцессор: оно заменяет указанное свойство на дословное значение .

Необходимо убедиться, что это дословное значение работает синтаксически в контексте целевой команды .

Как написано в настоящее время:

$SourceDirectoryPath = $(System.DefaultWorkingDirectory) + "/solution/project/bin/Debug"

превращается в следующую команду , видимую PowerShell , предполагая, что значение Azure свойство System.DefaultWorkingDirectory равно d:\a\r1\a':

$SourceDirectoryPath = d:\a\r1\a + "/solution/project/bin/Debug"

Это сломано n Команда PowerShell, поскольку d:\a\r1\a - из-за отсутствия цитирования - интерпретируется как имя команды или путь ; то есть сделана попытка выполнить предполагаемого исполняемого файла d:\a\r1\a - см. about_Parsing.

Следовательно, , чтобы PowerShell мог распознать Azure - расширенное значение d:\a\r1\a в виде строки , вам нужно указать это - см. about_Quoting_Rules.

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

$SourceDirectoryPath = '$(System.DefaultWorkingDirectory)' + '/solution/project/bin/Debug'

На самом деле, вам вообще не нужна конкатенация строк (+) в вашем случае:

$SourceDirectoryPath = '$(System.DefaultWorkingDirectory)/solution/project/bin/Debug'

Вы можете даже комбинировать это с расширяемыми строками PowerShell ("...") ), если в Azure -расширенном значении отсутствуют $ -префиксированные токены, которые PowerShell может в итоге интерпретировать (если это не ваше (необычное) намерение).

One caveat что-то вроде "$(System.DefaultWorkingDirectory)/$projectRoot/bin/Debug" (смешивание Azure -расширенного значения со ссылкой на переменную PowerShell) в том, что Azure * макрос синтаксис (* 10 95 *) выглядит так же, как собственный оператор подвыражения PowerShell , который обычно - но не исключительно - используется для встраивания выражений в расширяемые строки (например, в чистый PowerShell code, "1 + 1 equals $(1 + 1)").

На момент написания этой статьи Определить переменные Azure help topi c не прописывает это, а выдает официальный запрос комментарий в выпуске документации GitHub , устранена неоднозначность следующим образом :

  • Существует no механизм выхода; вместо этого конструкции $(...), которые не относятся к Azure переменным, оставлены без изменений и, следовательно, переданы через в PowerShell.

  • In в типичном случае выражения PowerShell не будут выглядеть как Azure ссылка на переменную (например, $($foo.bar), а не $(foo.bar)), хотя гипотетически может быть неоднозначность: $(hostname), что является допустимым Подвыражение PowerShell может быть вытеснено Azure, если определена переменная hostname Azure.

    • В таком угловом случае решение состоит в том, чтобы избежать использования inline сценарий и вместо этого поместите код во внешний файл сценария .
1 голос
/ 22 января 2020

Вам необходимо добавить кавычки " " в переменные:

$SourceDirectoryPath = "$(System.DefaultWorkingDirectory)" + "/solution/project/bin/Debug"
$TargetFilePath = "$(System.DefaultWorkingDirectory)" + "/solution/project/bin/Debug/" + "$(Release.ReleaseName)" + "$(Release.EnvironmentName)"
0 голосов
/ 22 января 2020

Это должно сработать. $ () вне двойных кавычек будет использоваться только для объединения двух или более операторов. Большинство людей даже не знают об этом.

Это на самом деле неверно. Я не знал Azure Синтаксис конвейера. Это просто показывает, насколько запутанным может быть сочетание Powershell и Azure Pipeline. Это сработало бы, если бы $ System был объектом Powershell, а не макросом Azure.

$SourceDirectoryPath = $System.DefaultWorkingDirectory + '/solution/project/bin/Debug'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...