Visual Studio 2008 блокирует пользовательские сборки задач MSBuild - PullRequest
28 голосов
/ 30 июля 2010

Я занимаюсь разработкой пользовательской задачи MSBuild, которая создает слой ORM , и использую его в проекте.Мне мешает поведение Visual Studio удерживать библиотеки задач MSBuild и не отпускать их.

Я бы хотел организовать свое решение следующим образом:

My Solution
 |
 +- (1) ORM Layer Custom Task Project
 |  |
 |  +- BuildOrmLayerTask.cs     // here's my task
 |  
 +- (2) Business Logic Project  // and here's the project that uses it.
    |
    +- <UsingTask TaskName="BuildOrmLayerTask" AssemblyFile="$(TaskAssembly)" />

Однако при сборке проекта (2) он фиксируется на сборке из проекта (1).Так что теперь я не могу собрать проект (1) снова, не закрыв решение и не открыв его снова.

Можно ли как-то организовать вещи так, чтобы пользовательская задача сборки не блокировалась Visual Studio?

Ответы [ 3 ]

26 голосов
/ 04 августа 2010

( Edit: Сайед Ибрагим Хашими , который буквально написал книгу о msbuild, предлагает класс AppDomainIsolatedTask для лучшего подхода)

Мне удалось решить это самому ...

Нашел сообщение на форуме от Дэна Мозли , одного из разработчиков MSBuild от Microsoft:

Привет,

К сожалению, это связано с тем, что MSBuild загружает сборки задач в основном домене приложения.CLR не позволяет выгрузить сборки из домена приложения, поскольку это позволяет проводить важные оптимизации с их стороны.

Единственный способ, который я предлагаю, - это вызвать tomsbuild.exe для сборки проектов, использующих задачу.Для этого создайте MSBuild.exe <> в качестве внешнего инструмента в VS.

Dan
разработчик в msbuild
DanMoseley - MSFT

Итак, похоже, чтоЧтобы снять блокировки, вы должны создать новый процесс MSBuild.exe.Это не может быть тот, который работает в Visual Studio, потому что, когда MSBuild работает, он загружает задачи в основной домен приложения Visual Studio, и это никогда не может быть выгружено.

  • создатьновый проект MSBuild (.csproj или аналогичный), который переопределяет цель 'Build' и выполняет ваши пользовательские действия, например:

    <!-- fragment of Prebuild.csproj -->   
    <Target Name="Build">   
         <BuildOrmLayerTask Repository="$(Repository)" />   
    </Target>
    
  • Добавьте его в Visual Studio, если хотите, ноиспользуйте Configuration Manager, чтобы убедиться, что он не встроен в любую конфигурацию.Просто позвольте VS позаботиться об управлении исходным кодом и т.п., а не о сборке.

  • Отредактируйте файл .csproj проекта, который зависит от Prebuild.csproj.Добавьте цель BeforeBuild, которая вызывает MSBuild с помощью задачи Exec.Это запустит новый процесс, и когда этот процесс завершится, блокировки файлов будут сняты.Пример;

    <PropertyGroup>   
         <PrebuildProject>$(SolutionDir)Prebuild\Prebuild.csproj</PrebuildProject>   
    </PropertyGroup>   
    <Target Name="BeforeBuild">   
         <Exec Command="msbuild.exe &quot;$(PrebuildProject)&quot;" />   
    </Target>
    

Теперь, когда вы строите зависимый проект, он выполняет MSBuild в новом процессе перед запуском компиляции.

4 голосов
/ 04 августа 2010

Можете ли вы отредактировать файлы проекта и включить следующее объявление свойства

<PropertyGroup>
    <GenerateResourceNeverLockTypeAssemblies>true</GenerateResourceNeverLockTypeAssemblies>
</PropertyGroup>

Дайте мне знать, если это работает для вас.

3 голосов
/ 10 июля 2014

Как я уже упоминал в комментарии, направленном на @ Al-Muhandis, представляется возможным создать оболочку вокруг пользовательской задачи так, чтобы оболочка блокировалась, но не была DLL-библиотекой пользовательской задачи. Я сделал первый шаг к этому с проектом изолированные задачи . Возможно, он глючит, и пока работает только с VS2008. Запросы на извлечение приветствуются.

Идея проекта была основана на наблюдении, что задачи, производные от MarshalByRefObject (используя, возможно, AppDomainIsolatedTask), по-видимому, загружаются в основной домен приложения для целей отражения, но создается новый домен приложения выполнить задание Поскольку загрузка в основной домен приложения по-прежнему блокирует библиотеку DLL, было полезно создать библиотеку DLL с задачей, производной от AppDomainIsolatedTask, которая загружает библиотеки пользовательских задач. Таким образом, DLL-оболочка блокируется, но, поскольку она выполняется в своем собственном домене приложения, DLL-файлы пользовательских задач выгружаются при выгрузке исполняющего домена задачи-оболочки. Эта процедура позволяет избежать блокировки библиотек пользовательских задач после завершения сборки.

...