Как я могу выполнять программы в моем%PATH% с MSBuild?
Примечание: я использую Mercurial в качестве примера здесь, потому что это то, что я пытаюсь заставить работать с MSBuild прямо сейчас.
Но проблема не ограничивается Mercurial, это происходит с каждой внешней программой, которая находится где-то в моем %PATH%
переменная (я пробовал то же самое с PowerShell, например).
Поэтому я не ставил метку Mercurial на этот вопрос специально, потому что это не про Mercurial!
Что я на самом деле хочу сделать:
Я хочу, чтобы мой скрипт сборки получил текущий номер ревизии из моего репозитория Mercurial и сохранил его в файле.
Самый простой способ сделать это из командной строки:
hg id -i >rev.txt
Mercurial установлен на моей машине и папка установки находится в моем %PATH%
переменная.
Таким образом, я могу запустить эту строку из любого места на моем компьютере (непосредственно из командной строки или из командного файла), и она просто работает.
Проблема возникает, когда я пытаюсь запустить эту строку из моего скрипта сборки.
Я меняю BeforeBuild
(или же AfterBuild
) раздел моего.csproj файла следующим образом:
<Target Name="AfterBuild">
<Exec Command="hg id -i >rev.txt"/>
</Target>
Когда я компилирую свое решение с помощью Visual Studio, оно работает, и файл rev.txt создается в папке, где находится мой.csproj.
Но когда я компилирую точно такое же решение из командной строки с MSBuild, сборка завершается неудачно со следующим сообщением об ошибке:
Команда "hg id -i >rev.txt" завершена с кодом 9009.
Я погуглил "msbuild code 9009" и нашел несколько решений, но все они предлагают предоставить полный путь к исполняемому файлу.
Когда я делаю это, сборка также успешно выполняется с MSBuild.
Но это не приемлемое для меня решение, потому что я не могу быть уверен, что все, кто использует мой проект (включая сервер сборки), установили Mercurial в одну и ту же папку.
Это именно то, что %PATH%
для...
То же самое происходит, когда я ставлю <Exec Command="...
строка прямо в скрипт сборки.
Если я указываю путь к исполняемому файлу, он работает.
Если я не укажу путь, это не так.
Есть ли хитрость, чтобы заставить MSBuild выполнять программы в моем %PATH%
переменная без указания полной папки?
РЕДАКТИРОВАТЬ:
@leppie:
Перенаправление вывода:
Вы имеете в виду тот факт, что я сохраняю вывод моей команды в текстовом файле внутри команды, а не просто запускаю hg id -i
в качестве команды и используя выходной параметр или что-то подобное, чтобы получить вывод?
Не имеет значения... ошибка та же, когда я опускаю >rev.txt
,
Аргументы командной строки:
Нет, он выдает ту же ошибку, даже если я сокращаю команду до hg
(без каких-либо параметров).
Не забывайте: если я запускаю точно такую же команду Exec в том же файле.csproj из Visual Studio, или если я просто указываю путь к файлу.exe в команде, все работает.
Так что перенаправление вывода IMO и аргументы командной строки не могут быть проблемой.
2 ответа
Хорошо, я нашел решение.
Я должен признать, что это был классический случай PEBKAC:-)
Я все равно объясню, может быть, это поможет тому, кто совершил ту же ошибку:
В основном все, что я пробовал (плюс то, что Джеймс Вулфенден предложил в своем ответе), сработало бы... если бы только командный файл, который я использую для запуска сценария сборки, не выглядел бы так:
path="%windir%\Microsoft.net\Framework\v4.0.30319"
msbuild build.proj
Да, точно.
Я редактирую %PATH%
переменная для продолжительности этого пакетного файла, и я перезаписываю его путем к MSBuild, а не просто добавляю его.
Поэтому, когда мой скрипт сборки пытается вызвать Mercurial, он больше не может его найти, потому что его местоположение не находится в %PATH%
Переменная больше.
Понятия не имею, почему я этого раньше не видел.
Правильный способ - добавить путь MSBuild, оставив другие пути без изменений:
path=%path%;%windir%\Microsoft.net\Framework\v4.0.30319
Вы пробовали этот пакет расширений для mercurial / msbuild? http://msbuildhg.codeplex.com/documentation
Кажется, есть задача для возврата идентификатора ревизии, чего нет у вас?
<HgVersion LocalPath="$(MSBuildProjectDirectory)" Timeout="5000">
<Output TaskParameter="Revision" PropertyName="AssemblyRevision" />
</HgVersion>