Собственная задача MSBuild блокирует сборку - PullRequest
16 голосов
/ 16 декабря 2010

На первый взгляд, моя проблема казалась обычной: в некоторых моих проектах у меня есть пользовательская задача MS Build.После компиляции проектов я больше не могу компилировать задачу сборки - сборка задачи сборки блокируется Visual Studio.

Я обнаружил здесь много постов, говорящих «Просто наследуй от AppDomainIsolatedTask».

Моя задача уже выполнена.Сборка не содержит ничего, кроме этой задачи.Кажется, что AppDomain выгружен, по крайней мере, событие DomainUnload сработало.И зависимые сборки выгружаются правильно.

Однако сборка, содержащая саму задачу сборки, заблокирована программой devenv.exe (которую я дважды проверил с помощью ProcessExplorer).

Я обнаружил еще один пост, в котором говорится «Установите свойство GenerateResourceNeverLockTypeAssemblies в значение true», котороезвучало многообещающе, но не помогло.

Итак, мне интересно, что еще может пойти не так.Поведение одинаково, независимо от того, использую я VS2008 или 2010.

Ответы [ 2 ]

1 голос
/ 29 мая 2018

Подобные вещи могут быть очень сложными, чтобы получить право. Существует множество факторов, которые следует учитывать в LoaderOptimization, ShadowCopy и т. Д.

AppDomainIsolatedTask не означает «не загрязнять домен сборки». Это означает «запустить мой код в другом домене» - сам тип задачи все еще загружен в домен механизма сборки. Это прискорбно, так как я чувствую, что большинство людей интерпретируют это как первое. Чтобы этот специализированный тип задачи работал, вы также должны декоратировать свою задачу с помощью [LoadInSeparateAppDomain]. Это все еще не решит вашу проблему.

ProcessExplorer имеет это удобное представление сборок .NET, которое вы можете использовать, чтобы определить, какой домен имеет дескриптор вашей сборки. Как вы уже знаете, devenv.exe заблокирован.

Useful feature

Поскольку вы загружаете DLL-библиотеку, которая выполняет задачу, в домен, который VS использует для создания материала, вы столкнетесь с этой проблемой.

Что вам нужно сделать, это ввести еще один слой косвенности.

Опция

  1. Вы можете преобразовать свою задачу в задачу со встроенным кодом .
  2. Вы можете использовать задачу встроенного кода, чтобы загрузить статическую задачу и делегировать ее.

Я привел пример для подхода № 2 Этот снимок экрана подтверждает результаты, что моя пользовательская библиотека отсутствует в домене приложения MSBuild.

Определите встроенное задание следующим образом:

<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  
  <UsingTask  
    TaskName="RunOtherTask"  
    TaskFactory="CodeTaskFactory"  AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >  
    <ParameterGroup />  
    <Task>
      <Using Namespace="MyTasks" />  
      <Code Type="Class" Language="cs">  
<![CDATA[ 
using System;  
using System.Reflection;
using Microsoft.Build.Framework;  
using Microsoft.Build.Utilities;  

namespace MyTasks {      
    public class RunOtherTask : Task {  
        public override bool Execute() { 
           var remoteTask = CreateInstanceInSeparateDomain();      
           remoteTask.BuildEngine = this.BuildEngine;
           remoteTask.Execute();

           return true;  
        }

        private ITask CreateInstanceInSeparateDomain() {
            var thisAssembly = Assembly.GetExecutingAssembly();

            var setup = new AppDomainSetup {
                ShadowCopyFiles = true.ToString(),              
                LoaderOptimization = LoaderOptimization.MultiDomainHost                 
            };

            var domain = AppDomain.CreateDomain("MyDomain", null, setup);
            var handle = domain.CreateInstanceFrom(@"C:\ClassLibrary1.dll", "ClassLibrary1.SimpleTask");

            return (ITask)handle.Unwrap();
        }
    }
} 
 ]]>
      </Code>  
    </Task>  
  </UsingTask>  

  <Target Name="RunTask">  
    <RunOtherTask /> 
  </Target>

</Project>  

Пока ваша задача реализует ITask (что она должна), она будет работать. Вам нужно установить свойство engine в только что созданной задаче, чтобы все работало правильно.

Class Library1 is not loaded

0 голосов
/ 02 августа 2011

Это может быть решено путем изменения безопасности разрешений файловой системы. поставить вашего текущего пользователя как совладельца заблокированного файла.

...