Как вызвать 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.
Ответы
Ответ 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.