Подтвердить что ты не робот

Как вызвать MSBuild из PowerShell с помощью & operator?

Я только что протестировал это на PowerShell v1.0. Настройка выполняется следующим образом:

 Id CommandLine
 -- -----------
  1 $msbuild = "C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe"
  4 $a = "C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build"

.

Эта строка выходит из строя с неинтуитивным сообщением об ошибке:

 Id CommandLine
 -- -----------
  5 & $msbuild $a

.

Эта строка терпит неудачу, потому что и ожидает, что первым аргументом будет сама команда.

 Id CommandLine
 -- -----------
 10 & "$msbuild $a"

.

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

 Id CommandLine
 -- -----------
 16 cmd /c "$msbuild $a"

.

Пожалуйста, объясните. Меня больше интересует, почему синтаксис не работает, чем способ обхода MSBuild.

4b9b3361

Ответ 1

Проблемы, которые вы видите в результате анализа аргументов PowerShell. В первом примере, когда PowerShell видит $a, он передает его как единственный параметр msbuild. Мы видим это с помощью утилиты echoargs из PSCX:.

PS> $a = "C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build"
PS> & echoargs $a
Arg 0 is <C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build>

Второй пример еще хуже, потому что вы говорите powershell о вызове "$ echoargs $a" в качестве имени команды, и это не допустимое имя команды.

Третья строка работает, потому что CMD.exe получает расширенную форму "$ echoargs $a" в качестве единственного аргумента, который анализирует и выполняет:

У вас есть пара вариантов. Сначала я делаю это следующим образом:

PS> & $msbuild C:\some\project\or\other\src\Solution.sln `
    /target:Clean /target:Build

Другой вариант - использовать Invoke-Expression следующим образом:

PS> Invoke-Expression "$msbuild $a"

В общем, я стараюсь быть очень осторожным с Invoke-Expression, особенно если какая-либо часть строки, которая вызывается, предоставляется пользователем.

Ответ 2

Тьфу.

$collectionOfArgs = @("C:\some\project\or\other\src\Solution.sln", 
    "/target:Clean", "/target:Build")
& $msbuild $collectionOfArgs

Это работает. и принимает набор аргументов, поэтому вы должны разделить строки, содержащие несколько аргументов, в набор строковых аргументов.

Ответ 3

Вы также можете попробовать использовать бесплатную Invoke-MsBuild powershell script/module. Это, по сути, дает вам командлет Invoke-MsBuild PowerShell, который вы можете вызывать, вместо того, чтобы пытаться самостоятельно вызвать файл msbuild.exe.