Использовать пользовательские задачи MSBuild из одного и того же решения?
Я новичок в MSBuild и хотел немного поиграть с ним, но я просто не могу понять, почему это не работает.
Итак, у моего решения есть два проекта: "Модель" и "BuildTasks". BuildTasks имеет только один класс:
using Microsoft.Build.Utilities;
namespace BuildTasks
{
public class Test : Task
{
public override bool Execute()
{
Log.LogMessage( "FASDfasdf" );
return true;
}
}
}
И затем в Model.csproj я добавил следующее:
<UsingTask TaskName="BuildTasks.Test" AssemblyFile="$(SolutionDir)src\BuildTasks\bin\BuildTasks.dll" />
<Target Name="AfterBuild">
<Test />
</Target>
Я установил порядок сборки, поэтому "BuildTasks" создается до "Модели". Но когда я пытаюсь построить модель, я получаю эту ошибку:
Задача "BuildTasks.Test" не могла загружаться из сборки C:\WIP\TestSolution\SRC\BuildTasks\Bin\BuildTasks.dll. Не удалось загрузить файл или сборку 'Файл:///C:\WIP\TestSolution\SRC\BuildTasks\Bin\BuildTasks.dll' или одной из его зависимостей. Система не может найти указанный файл. Убедитесь, что <UseTask> правильность декларации и что сборка и все ее зависимости доступны.
Этот файл определенно существует, поэтому почему MSBuild не может найти его?
Я даже попробовал жесткое кодирование "C:\WIP\TestSolution" вместо "$ (SolutionDir)" и получил ту же ошибку. Однако, если я скопирую этот .dll на свой рабочий стол и жестко программирую путь к моему рабочему столу, он работает, и я не могу понять, почему.
РЕДАКТИРОВАТЬ. Я не ошибаюсь. Я изменил сборки Debug/Release для BuildTasks, чтобы вывести .dll только в папку bin, так как я не хотел, чтобы Debug/Release имел разные пути.
Ответы
Ответ 1
Мы попробовали это, и мы обнаружили, что вы должны поместить UseTask в верхнюю часть файла проекта (и имеете все ваши пути справа). Однако, как только это произойдет, и задача загрузится, она будет работать только один раз. После этого сборка начинается с сбоя, потому что она не может скопировать DLL, в которой находится задача. Фактически мы запускаем задачу пост-сборки, которая находится внутри той же сборки/проекта, что и мы.
Что мы сделали для решения этой проблемы, так это запустить отдельный процесс MSBuild в отдельном файле MSBuild для запуска задач Post Build. Таким образом, DLL не загружается до момента ее создания и копирования в каталог bin.
<Target Name="AfterBuild">
<Exec Command="$(MSBuildBinPath)\MSBuild.exe
"$(MSBuildProjectDirectory)\PostBuild.msbuild"
/property:SomeProperty=$(SomeProperty)" />
</Target>
Обратите внимание, что вы можете передать свойства в эту задачу сборки в командной строке.
И PostBuild.msbuild выглядит так:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="PostBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<UsingTask TaskName="PostBuild" AssemblyFile="$(MSBuildProjectDirectory)\bin\AssemblyThatJustBuiltAndContainsBuildTask.dll" />
<PropertyGroup>
<SomeProperty>SomePropertyDefaultValue</SomeProperty>
</PropertyGroup>
<Target Name="PostBuild">
<MyPostBuildTask SomeProperty="$(SomeProperty)" />
</Target>
</Project>
Ответ 2
Slace было правильно. Скорее всего, ваш путь к сборке неверен. Вероятно, это должно быть:
<UsingTask
TaskName="BuildTasks.Test"
AssemblyFile="$(SolutionDir)src\BuildTasks\bin\$(Configuration)\BuildTasks.dll" />
<Target Name="AfterBuild">
<Test />
</Target>
Ответ 3
Вы уверены, что у вас есть путь к записи? Разве это не должно быть в bin\Configuration Type\BuildTasks.dll
?
Я нашел эту ссылку: http://bartdesmet.net/blogs/bart/archive/2008/02/15/the-custom-msbuild-task-cookbook.aspx очень полезно при запуске задач MSBuild.
Ответ 4
Отключение повторного использования MSBuild node также устранит эту проблему:
- В командной строке MSBuild передайте параметр
/nr:false
.
- Для Visual Studio вы должны установить переменную среды
MSBUILDDISABLENODEREUSE
в 1
перед запуском VS.
См. В RTM для Visual Studio 2012 есть MSBuild.exe в памяти после закрытия
Ответ 5
Вы можете попробовать fuslogvw, чтобы диагностировать проблему, подумал, что я неясен, если она дойдет до этого...
http://msdn.microsoft.com/en-us/library/e74a18c4.aspx
Ответ 6
Блокировка DLL настраиваемых задач можно избежать, если все пользовательские задачи наследуются от AppDomainIsolatedTask
и если вы установите переменную среды MSBUILDDISABLENODEREUSE = 1
перед запуском Visual Studio.
Сборка с задачами пользовательской сборки блокируется как с помощью файла devenv.exe, так и с помощью msbuild.exe.
Вы можете заставить процессы msbuild.exe уйти с MSBUILDDISABLENODEREUSE = 1
, но devenv.exe по-прежнему будет спорадически блокировать сборку настраиваемых задач, если ваши пользовательские задачи наследуются от Task.
С другой стороны, если вы только наследуете от AppDomainIsolatedTask и не устанавливаете MSBUILDDISABLENODEREUSE
, то незавершенные процессы MSBuild по-прежнему будут блокировать сборку.