This kind of thing can be very tricky to get right. There is a lot to consider LoaderOptimization, ShadowCopy etc.
AppDomainIsolatedTask
does not mean "do not pollute the build domain".
It means "run my code in another domain" - the task type itself is still loaded into the build engine domain. This is unfortunate as I feel most people interpret it as the former. For this specialized task type to work you must also decoarate your task with [LoadInSeparateAppDomain]
. This still will not solve your problem.
ProcessExplorer has this handy .NET assemblies view which you can use to identify which domain has a handle to your assembly. As you already know devenv.exe has it locked.

Since you load the DLL that has the task into the domain that VS uses for building stuff you are going to run into this problem.
What you need to do is introduce another layer of indirection.
Options
- You can convert your task to an inline code task.
- You can use an inline code task to load your static task and delegate to it.
I have provided an example for approach #2
This screenshot validates the results that my custom library is not present in the MSBuild appdomain.
Define a inline task like so
<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>
As long as your task implements ITask (which it must) it will work.
You need to set the engine property on the newly instantiated task for everything to work correctly.
