乍一看,我的问题似乎很常见:我的一些项目中有一个自定义的MS Build任务。编译项目后,我无法再编译构建任务 - 构建任务程序集被Visual Studio锁定。
我在这里发现很多帖子说“只是从AppDomainIsolatedTask继承”。
我的任务已经完成。该程序集除此任务外不包含其他内容。似乎卸载了AppDomain,至少触发了DomainUnload事件。并且,依赖程序集正确卸载。
但是,包含构建任务本身的程序集已被devenv.exe锁定(我已经过ProcessExplorer对其进行了双重检查)。
我发现另一篇文章说'将GenerateResourceNeverLockTypeAssemblies属性设置为true',听起来很有希望,但也没有帮助。
所以,我想知道还有什么可能出错。无论我使用VS2008还是2010,行为都是一样的。
答案 0 :(得分:0)
这样的事情可能非常棘手。有很多要考虑LoaderOptimization,ShadowCopy等。
AppDomainIsolatedTask
并不意味着"不污染构建域"。
这意味着"在另一个域中运行我的代码" - 任务类型本身仍然加载到构建引擎域中。这是不幸的,因为我觉得大多数人都把它解释为前者。要使此专用任务类型起作用,您还必须使用[LoadInSeparateAppDomain]
对任务进行装饰。这仍然无法解决您的问题。
ProcessExplorer具有这个方便的.NET程序集视图,您可以使用它来识别哪个域具有程序集句柄。正如您所知,devenv.exe已将其锁定。
由于您将具有任务的DLL加载到VS用于构建内容的域中,因此您将遇到此问题。
您需要做的是引入另一层间接。
选项强>
我提供了方法#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(它必须),它就会起作用。 您需要在新实例化的任务上设置引擎属性,以使一切正常工作。
答案 1 :(得分:-3)
可以通过更改文件系统权限安全性来解决。将您当前的用户设置为锁定文件的共同所有者。