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

Использовать пользовательские задачи 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 имел разные пути.

4b9b3361

Ответ 1

Мы попробовали это, и мы обнаружили, что вы должны поместить UseTask в верхнюю часть файла проекта (и имеете все ваши пути справа). Однако, как только это произойдет, и задача загрузится, она будет работать только один раз. После этого сборка начинается с сбоя, потому что она не может скопировать DLL, в которой находится задача. Фактически мы запускаем задачу пост-сборки, которая находится внутри той же сборки/проекта, что и мы.

Что мы сделали для решения этой проблемы, так это запустить отдельный процесс MSBuild в отдельном файле MSBuild для запуска задач Post Build. Таким образом, DLL не загружается до момента ее создания и копирования в каталог bin.

<Target Name="AfterBuild">
    <Exec Command="$(MSBuildBinPath)\MSBuild.exe 
          &quot;$(MSBuildProjectDirectory)\PostBuild.msbuild&quot; 
          /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>

Ответ 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 по-прежнему будут блокировать сборку.