/// <summary> /// We just need the loaded type information because the task factory which is not instance specific should /// already have loaded the assembly and got the information. /// </summary> public AssemblyTaskFactoryInstance(string taskName, LoadedType loadedType) { ErrorUtilities.VerifyThrowArgumentLength(taskName, "taskName"); ErrorUtilities.VerifyThrowArgumentNull(loadedType, "loadedType"); this.taskName = taskName; this.loadedType = loadedType; }
/// <summary> /// Check if we added a resolver and remove it /// </summary> internal static void RemoveAssemblyResolver() { if (s_resolverLoadedType != null) { AppDomain.CurrentDomain.AssemblyResolve -= AssemblyResolver; s_resolverLoadedType = null; } }
/// <summary> /// Creates an instance of this class for the given type. /// </summary> internal TaskFactoryWrapper(ITaskFactory taskFactory, LoadedType taskFactoryLoadInfo, string taskName, IDictionary<string, string> factoryIdentityParameters) { ErrorUtilities.VerifyThrowArgumentNull(taskFactory, "taskFactory"); ErrorUtilities.VerifyThrowArgumentLength(taskName, "taskName"); _taskFactory = taskFactory; _taskName = taskName; TaskFactoryLoadedType = taskFactoryLoadInfo; _factoryIdentityParameters = factoryIdentityParameters; }
/// <summary> /// Abstract out the creation of the new AssemblyTaskFactory with default task, and /// with some basic validation. /// </summary> private void SetupTaskFactory(IDictionary<string, string> factoryParameters, bool explicitlyLaunchTaskHost) { _taskFactory = new AssemblyTaskFactory(); _loadInfo = AssemblyLoadInfo.Create(null, Assembly.GetAssembly(typeof(TaskToTestFactories)).Location); _loadedType = _taskFactory.InitializeFactory(_loadInfo, "TaskToTestFactories", new Dictionary<string, TaskPropertyInfo>(), string.Empty, factoryParameters, explicitlyLaunchTaskHost, null, ElementLocation.Create("NONE"), String.Empty); Assert.True(_loadedType.Assembly.Equals(_loadInfo)); // "Expected the AssemblyLoadInfo to be equal" }
public void VerifyGetTaskParameters() { TaskPropertyInfo[] propertyInfos = _taskFactory.GetTaskParameters(); LoadedType comparisonType = new LoadedType(typeof(TaskToTestFactories), _loadInfo); PropertyInfo[] comparisonInfo = comparisonType.Type.GetProperties(BindingFlags.Instance | BindingFlags.Public); Assert.Equal(comparisonInfo.Length, propertyInfos.Length); bool foundExpectedParameter = false; bool foundNotExpectedParameter = false; for (int i = 0; i < propertyInfos.Length; i++) { if (propertyInfos[i].Name.Equals("ExpectedParameter", StringComparison.OrdinalIgnoreCase)) { foundExpectedParameter = true; } if (propertyInfos[i].Name.Equals("NotExpectedParameter", StringComparison.OrdinalIgnoreCase)) { foundNotExpectedParameter = true; } } Assert.True(foundExpectedParameter); Assert.False(foundNotExpectedParameter); }
/// <summary> /// Initialize the factory from the task registry /// </summary> internal LoadedType InitializeFactory ( AssemblyLoadInfo loadInfo, string taskName, IDictionary<string, TaskPropertyInfo> taskParameters, string taskElementContents, IDictionary<string, string> taskFactoryIdentityParameters, bool taskHostFactoryExplicitlyRequested, TargetLoggingContext targetLoggingContext, ElementLocation elementLocation, string taskProjectFile ) { ErrorUtilities.VerifyThrowArgumentNull(loadInfo, "loadInfo"); VerifyThrowIdentityParametersValid(taskFactoryIdentityParameters, elementLocation, taskName, "Runtime", "Architecture"); if (taskFactoryIdentityParameters != null) { _factoryIdentityParameters = new Dictionary<string, string>(taskFactoryIdentityParameters, StringComparer.OrdinalIgnoreCase); } _taskHostFactoryExplicitlyRequested = taskHostFactoryExplicitlyRequested; try { ErrorUtilities.VerifyThrowArgumentLength(taskName, "taskName"); _taskName = taskName; _loadedType = _typeLoader.Load(taskName, loadInfo); ProjectErrorUtilities.VerifyThrowInvalidProject(_loadedType != null, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, String.Empty); } catch (TargetInvocationException e) { // Exception thrown by the called code itself // Log the stack, so the task vendor can fix their code ProjectErrorUtilities.VerifyThrowInvalidProject(false, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, Environment.NewLine + e.InnerException.ToString()); } catch (ReflectionTypeLoadException e) { // ReflectionTypeLoadException.LoaderExceptions may contain nulls foreach (Exception exception in e.LoaderExceptions) { if (exception != null) { targetLoggingContext.LogError(new BuildEventFileInfo(taskProjectFile), "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, exception.Message); } } ProjectErrorUtilities.VerifyThrowInvalidProject(false, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, e.Message); } catch (ArgumentNullException e) { // taskName may be null ProjectErrorUtilities.VerifyThrowInvalidProject(false, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, e.Message); } catch (Exception e) // Catching Exception, but rethrowing unless it's a well-known exception. { if (ExceptionHandling.NotExpectedReflectionException(e)) { throw; } ProjectErrorUtilities.VerifyThrowInvalidProject(false, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, e.Message); } return _loadedType; }
/// <summary> /// Creates an ITask instance and returns it. /// </summary> internal static ITask CreateTask(LoadedType loadedType, string taskName, string taskLocation, int taskLine, int taskColumn, LogError logError #if FEATURE_APPDOMAIN , AppDomainSetup appDomainSetup #endif , bool isOutOfProc #if FEATURE_APPDOMAIN , out AppDomain taskAppDomain #endif ) { #if FEATURE_APPDOMAIN bool separateAppDomain = loadedType.HasLoadInSeparateAppDomainAttribute(); s_resolverLoadedType = null; taskAppDomain = null; ITask taskInstanceInOtherAppDomain = null; #endif try { #if FEATURE_APPDOMAIN if (separateAppDomain) { if (!loadedType.Type.GetTypeInfo().IsMarshalByRef) { logError ( taskLocation, taskLine, taskColumn, "TaskNotMarshalByRef", taskName ); return(null); } else { // Our task depend on this name to be precisely that, so if you change it make sure // you also change the checks in the tasks run in separate AppDomains. Better yet, just don't change it. // Make sure we copy the appdomain configuration and send it to the appdomain we create so that if the creator of the current appdomain // has done the binding redirection in code, that we will get those settings as well. AppDomainSetup appDomainInfo = new AppDomainSetup(); // Get the current app domain setup settings byte[] currentAppdomainBytes = appDomainSetup.GetConfigurationBytes(); // Apply the appdomain settings to the new appdomain before creating it appDomainInfo.SetConfigurationBytes(currentAppdomainBytes); if (BuildEnvironmentHelper.Instance.RunningTests) { // Prevent the new app domain from looking in the VS test runner location. If this // is not done, we will not be able to find Microsoft.Build.* assemblies. appDomainInfo.ApplicationBase = BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory; appDomainInfo.ConfigurationFile = BuildEnvironmentHelper.Instance.CurrentMSBuildConfigurationFile; } else { // Set the taskAppDomain's BaseDirectory to the one containing the msbuild assemblies // This host assembly might not be MSBuild.exe and so could be in a different location, // so, look for a type in Microsoft.Build.dll appDomainInfo.ApplicationBase = Path.GetDirectoryName(typeof(Microsoft.Build.Execution.ProjectInstance).Assembly.Location); } AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver; s_resolverLoadedType = loadedType; taskAppDomain = AppDomain.CreateDomain(isOutOfProc ? "taskAppDomain (out-of-proc)" : "taskAppDomain (in-proc)", null, appDomainInfo); if (loadedType.LoadedAssembly != null) { taskAppDomain.Load(loadedType.LoadedAssembly.GetName()); } #if FEATURE_APPDOMAIN_UNHANDLED_EXCEPTION // Hook up last minute dumping of any exceptions taskAppDomain.UnhandledException += new UnhandledExceptionEventHandler(ExceptionHandling.UnhandledExceptionHandler); #endif } } else #endif { // perf improvement for the same appdomain case - we already have the type object // and don't want to go through reflection to recreate it from the name. return((ITask)Activator.CreateInstance(loadedType.Type)); } #if FEATURE_APPDOMAIN if (loadedType.Assembly.AssemblyFile != null) { taskInstanceInOtherAppDomain = (ITask)taskAppDomain.CreateInstanceFromAndUnwrap(loadedType.Assembly.AssemblyFile, loadedType.Type.FullName); // this will force evaluation of the task class type and try to load the task assembly Type taskType = taskInstanceInOtherAppDomain.GetType(); // If the types don't match, we have a problem. It means that our AppDomain was able to load // a task assembly using Load, and loaded a different one. I don't see any other choice than // to fail here. if (taskType != loadedType.Type) { logError ( taskLocation, taskLine, taskColumn, "ConflictingTaskAssembly", loadedType.Assembly.AssemblyFile, loadedType.Type.GetTypeInfo().Assembly.Location ); taskInstanceInOtherAppDomain = null; } } else { taskInstanceInOtherAppDomain = (ITask)taskAppDomain.CreateInstanceAndUnwrap(loadedType.Type.GetTypeInfo().Assembly.FullName, loadedType.Type.FullName); } return(taskInstanceInOtherAppDomain); #endif } finally { #if FEATURE_APPDOMAIN // Don't leave appdomains open if (taskAppDomain != null && taskInstanceInOtherAppDomain == null) { AppDomain.Unload(taskAppDomain); RemoveAssemblyResolver(); } #endif } }
/// <summary> /// Initialize the host object /// </summary> /// <param name="throwOnExecute">Should the task throw when executed</param> private void InitializeHost(bool throwOnExecute) { _loggingService = LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1) as ILoggingService; _logger = new MockLogger(); _loggingService.RegisterLogger(_logger); _host = new TaskExecutionHost(); TargetLoggingContext tlc = new TargetLoggingContext(_loggingService, new BuildEventContext(1, 1, BuildEventContext.InvalidProjectContextId, 1)); // Set up a temporary project and add some items to it. ProjectInstance project = CreateTestProject(); TypeLoader typeLoader = new TypeLoader(new TypeFilter(IsTaskFactoryClass)); AssemblyLoadInfo loadInfo = AssemblyLoadInfo.Create(Assembly.GetAssembly(typeof(TaskBuilderTestTask.TaskBuilderTestTaskFactory)).FullName, null); LoadedType loadedType = new LoadedType(typeof(TaskBuilderTestTask.TaskBuilderTestTaskFactory), loadInfo); TaskBuilderTestTask.TaskBuilderTestTaskFactory taskFactory = new TaskBuilderTestTask.TaskBuilderTestTaskFactory(); taskFactory.ThrowOnExecute = throwOnExecute; string taskName = "TaskBuilderTestTask"; (_host as TaskExecutionHost)._UNITTESTONLY_TaskFactoryWrapper = new TaskFactoryWrapper(taskFactory, loadedType, taskName, null); _host.InitializeForTask ( this, tlc, project, taskName, ElementLocation.Create("none", 1, 1), this, false, null, false, CancellationToken.None ); ProjectTaskInstance taskInstance = project.Targets["foo"].Tasks.First(); TaskLoggingContext talc = tlc.LogTaskBatchStarted(".", taskInstance); ItemDictionary<ProjectItemInstance> itemsByName = new ItemDictionary<ProjectItemInstance>(); ProjectItemInstance item = new ProjectItemInstance(project, "ItemListContainingOneItem", "a.cs", "."); item.SetMetadata("Culture", "fr-fr"); itemsByName.Add(item); _oneItem = new ITaskItem[] { new TaskItem(item) }; item = new ProjectItemInstance(project, "ItemListContainingTwoItems", "b.cs", "."); ProjectItemInstance item2 = new ProjectItemInstance(project, "ItemListContainingTwoItems", "c.cs", "."); item.SetMetadata("HintPath", "c:\\foo"); item2.SetMetadata("HintPath", "c:\\bar"); itemsByName.Add(item); itemsByName.Add(item2); _twoItems = new ITaskItem[] { new TaskItem(item), new TaskItem(item2) }; _bucket = new ItemBucket(new string[0], new Dictionary<string, string>(), new Lookup(itemsByName, new PropertyDictionary<ProjectPropertyInstance>(), null), 0); _host.FindTask(null); _host.InitializeForBatch(talc, _bucket, null); _parametersSetOnTask = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); _outputsReadFromTask = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); }
/// <summary> /// Do the work of actually instantiating and running the task. /// </summary> private OutOfProcTaskHostTaskResult InstantiateAndExecuteTask ( IBuildEngine oopTaskHostNode, LoadedType taskType, string taskName, string taskLocation, string taskFile, int taskLine, int taskColumn, AppDomainSetup appDomainSetup, IDictionary<string, TaskParameter> taskParams ) { _taskAppDomain = null; _wrappedTask = null; try { _wrappedTask = TaskLoader.CreateTask(taskType, taskName, taskFile, taskLine, taskColumn, new TaskLoader.LogError(LogErrorDelegate), appDomainSetup, true /* always out of proc */, out _taskAppDomain); Type wrappedTaskType = _wrappedTask.GetType(); _wrappedTask.BuildEngine = oopTaskHostNode; } catch (Exception e) { if (ExceptionHandling.IsCriticalException(e)) { throw; } Exception exceptionToReturn = e; // If it's a TargetInvocationException, we only care about the contents of the inner exception, // so just save that instead. if (e is TargetInvocationException) { exceptionToReturn = e.InnerException; } return new OutOfProcTaskHostTaskResult ( TaskCompleteType.CrashedDuringInitialization, exceptionToReturn, "TaskInstantiationFailureError", new string[] { taskName, taskLocation, String.Empty } ); } foreach (KeyValuePair<string, TaskParameter> param in taskParams) { try { PropertyInfo paramInfo = _wrappedTask.GetType().GetProperty(param.Key, BindingFlags.Instance | BindingFlags.Public); paramInfo.SetValue(_wrappedTask, (param.Value == null ? null : param.Value.WrappedParameter), null); } catch (Exception e) { if (ExceptionHandling.IsCriticalException(e)) { throw; } Exception exceptionToReturn = e; // If it's a TargetInvocationException, we only care about the contents of the inner exception, // so just save that instead. if (e is TargetInvocationException) { exceptionToReturn = e.InnerException; } return new OutOfProcTaskHostTaskResult ( TaskCompleteType.CrashedDuringInitialization, exceptionToReturn, "InvalidTaskAttributeError", new string[] { param.Key, param.Value.ToString(), taskName } ); } } bool success = false; try { if (CancelPending) { return new OutOfProcTaskHostTaskResult(TaskCompleteType.Failure); } // If it didn't crash and return before now, we're clear to go ahead and execute here. success = _wrappedTask.Execute(); } catch (Exception e) { if (ExceptionHandling.IsCriticalException(e)) { throw; } return new OutOfProcTaskHostTaskResult(TaskCompleteType.CrashedDuringExecution, e); } PropertyInfo[] finalPropertyValues = _wrappedTask.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); IDictionary<string, Object> finalParameterValues = new Dictionary<string, Object>(StringComparer.OrdinalIgnoreCase); foreach (PropertyInfo value in finalPropertyValues) { // only record outputs if (value.GetCustomAttributes(typeof(OutputAttribute), true).Length > 0) { try { finalParameterValues[value.Name] = value.GetValue(_wrappedTask, null); } catch (Exception e) { if (ExceptionHandling.IsCriticalException(e)) { throw; } // If it's not a critical exception, we assume there's some sort of problem in the parameter getter -- // so save the exception, and we'll re-throw once we're back on the main node side of the // communications pipe. finalParameterValues[value.Name] = e; } } } return new OutOfProcTaskHostTaskResult(success ? TaskCompleteType.Success : TaskCompleteType.Failure, finalParameterValues); }
public void TearDownAttribute() { _taskFactory = null; _loadInfo = null; _loadedType = null; }
/// <summary> /// Execute a task on the STA thread. /// </summary> /// <comment> /// STA thread launching code lifted from XMakeBuildEngine\BackEnd\Components\RequestBuilder\TaskBuilder.cs, ExecuteTaskInSTAThread method. /// Any bug fixes made to this code, please ensure that you also fix that code. /// </comment> private OutOfProcTaskHostTaskResult InstantiateAndExecuteTaskInSTAThread ( IBuildEngine oopTaskHostNode, LoadedType taskType, string taskName, string taskLocation, string taskFile, int taskLine, int taskColumn, AppDomainSetup appDomainSetup, IDictionary<string, TaskParameter> taskParams ) { ManualResetEvent taskRunnerFinished = new ManualResetEvent(false); OutOfProcTaskHostTaskResult taskResult = null; Exception exceptionFromExecution = null; try { ThreadStart taskRunnerDelegate = delegate () { try { taskResult = InstantiateAndExecuteTask ( oopTaskHostNode, taskType, taskName, taskLocation, taskFile, taskLine, taskColumn, appDomainSetup, taskParams ); } catch (Exception e) { if (ExceptionHandling.IsCriticalException(e)) { throw; } exceptionFromExecution = e; } finally { taskRunnerFinished.Set(); } }; Thread staThread = new Thread(taskRunnerDelegate); staThread.SetApartmentState(ApartmentState.STA); staThread.Name = "MSBuild STA task runner thread"; staThread.CurrentCulture = Thread.CurrentThread.CurrentCulture; staThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture; staThread.Start(); // TODO: Why not just Join on the thread??? taskRunnerFinished.WaitOne(); } finally { taskRunnerFinished.Close(); taskRunnerFinished = null; } if (exceptionFromExecution != null) { // Unfortunately this will reset the callstack throw exceptionFromExecution; } return taskResult; }
/// <summary> /// Creates an ITask instance and returns it. /// </summary> internal static ITask CreateTask(LoadedType loadedType, string taskName, string taskLocation, int taskLine, int taskColumn, LogError logError, AppDomainSetup appDomainSetup, bool isOutOfProc, out AppDomain taskAppDomain) { bool separateAppDomain = loadedType.HasLoadInSeparateAppDomainAttribute(); s_resolverLoadedType = null; taskAppDomain = null; ITask taskInstanceInOtherAppDomain = null; try { if (separateAppDomain) { if (!loadedType.Type.IsMarshalByRef) { logError ( taskLocation, taskLine, taskColumn, "TaskNotMarshalByRef", taskName ); return null; } else { // Our task depend on this name to be precisely that, so if you change it make sure // you also change the checks in the tasks run in separate AppDomains. Better yet, just don't change it. // Make sure we copy the appdomain configuration and send it to the appdomain we create so that if the creator of the current appdomain // has done the binding redirection in code, that we will get those settings as well. AppDomainSetup appDomainInfo = new AppDomainSetup(); // Get the current app domain setup settings byte[] currentAppdomainBytes = appDomainSetup.GetConfigurationBytes(); // Apply the appdomain settings to the new appdomain before creating it appDomainInfo.SetConfigurationBytes(currentAppdomainBytes); AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver; s_resolverLoadedType = loadedType; taskAppDomain = AppDomain.CreateDomain(isOutOfProc ? "taskAppDomain (out-of-proc)" : "taskAppDomain (in-proc)", null, appDomainInfo); if (loadedType.LoadedAssembly != null) { taskAppDomain.Load(loadedType.LoadedAssembly.GetName()); } // Hook up last minute dumping of any exceptions taskAppDomain.UnhandledException += new UnhandledExceptionEventHandler(ExceptionHandling.UnhandledExceptionHandler); } } else { // perf improvement for the same appdomain case - we already have the type object // and don't want to go through reflection to recreate it from the name. return (ITask)Activator.CreateInstance(loadedType.Type); } if (loadedType.Assembly.AssemblyFile != null) { taskInstanceInOtherAppDomain = (ITask)taskAppDomain.CreateInstanceFromAndUnwrap(loadedType.Assembly.AssemblyFile, loadedType.Type.FullName); // this will force evaluation of the task class type and try to load the task assembly Type taskType = taskInstanceInOtherAppDomain.GetType(); // If the types don't match, we have a problem. It means that our AppDomain was able to load // a task assembly using Load, and loaded a different one. I don't see any other choice than // to fail here. if (taskType != loadedType.Type) { logError ( taskLocation, taskLine, taskColumn, "ConflictingTaskAssembly", loadedType.Assembly.AssemblyFile, loadedType.Type.Assembly.Location ); taskInstanceInOtherAppDomain = null; } } else { taskInstanceInOtherAppDomain = (ITask)taskAppDomain.CreateInstanceAndUnwrap(loadedType.Type.Assembly.FullName, loadedType.Type.FullName); } return taskInstanceInOtherAppDomain; } finally { // Don't leave appdomains open if (taskAppDomain != null && taskInstanceInOtherAppDomain == null) { AppDomain.Unload(taskAppDomain); RemoveAssemblyResolver(); } } }
/// <summary> /// Constructor /// </summary> public TaskHostTask(IElementLocation taskLocation, TaskLoggingContext taskLoggingContext, IBuildComponentHost buildComponentHost, IDictionary<string, string> taskHostParameters, LoadedType taskType, AppDomainSetup appDomainSetup) { ErrorUtilities.VerifyThrowInternalNull(taskType, "taskType"); _taskLocation = taskLocation; _taskLoggingContext = taskLoggingContext; _buildComponentHost = buildComponentHost; _taskType = taskType; _appDomainSetup = appDomainSetup; _taskHostParameters = taskHostParameters; _packetFactory = new NodePacketFactory(); (this as INodePacketFactory).RegisterPacketHandler(NodePacketType.LogMessage, LogMessagePacket.FactoryForDeserialization, this); (this as INodePacketFactory).RegisterPacketHandler(NodePacketType.TaskHostTaskComplete, TaskHostTaskComplete.FactoryForDeserialization, this); (this as INodePacketFactory).RegisterPacketHandler(NodePacketType.NodeShutdown, NodeShutdown.FactoryForDeserialization, this); _packetReceivedEvent = new AutoResetEvent(false); _receivedPackets = new Queue<INodePacket>(); _taskHostLock = new Object(); _setParameters = new Dictionary<string, object>(); }
/// <summary> /// Creates an ITask instance and returns it. /// </summary> internal static ITask CreateTask(LoadedType loadedType, string taskName, string taskLocation, int taskLine, int taskColumn, LogError logError, AppDomainSetup appDomainSetup, bool isOutOfProc, out AppDomain taskAppDomain) { bool separateAppDomain = loadedType.HasLoadInSeparateAppDomainAttribute(); s_resolverLoadedType = null; taskAppDomain = null; ITask taskInstanceInOtherAppDomain = null; try { if (separateAppDomain) { if (!loadedType.Type.IsMarshalByRef) { logError ( taskLocation, taskLine, taskColumn, "TaskNotMarshalByRef", taskName ); return(null); } else { // Our task depend on this name to be precisely that, so if you change it make sure // you also change the checks in the tasks run in separate AppDomains. Better yet, just don't change it. // Make sure we copy the appdomain configuration and send it to the appdomain we create so that if the creator of the current appdomain // has done the binding redirection in code, that we will get those settings as well. AppDomainSetup appDomainInfo = new AppDomainSetup(); // Get the current app domain setup settings byte[] currentAppdomainBytes = appDomainSetup.GetConfigurationBytes(); // Apply the appdomain settings to the new appdomain before creating it appDomainInfo.SetConfigurationBytes(currentAppdomainBytes); AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver; s_resolverLoadedType = loadedType; taskAppDomain = AppDomain.CreateDomain(isOutOfProc ? "taskAppDomain (out-of-proc)" : "taskAppDomain (in-proc)", null, appDomainInfo); if (loadedType.LoadedAssembly != null) { taskAppDomain.Load(loadedType.LoadedAssembly.GetName()); } // Hook up last minute dumping of any exceptions taskAppDomain.UnhandledException += new UnhandledExceptionEventHandler(ExceptionHandling.UnhandledExceptionHandler); } } else { // perf improvement for the same appdomain case - we already have the type object // and don't want to go through reflection to recreate it from the name. return((ITask)Activator.CreateInstance(loadedType.Type)); } if (loadedType.Assembly.AssemblyFile != null) { taskInstanceInOtherAppDomain = (ITask)taskAppDomain.CreateInstanceFromAndUnwrap(loadedType.Assembly.AssemblyFile, loadedType.Type.FullName); // this will force evaluation of the task class type and try to load the task assembly Type taskType = taskInstanceInOtherAppDomain.GetType(); // If the types don't match, we have a problem. It means that our AppDomain was able to load // a task assembly using Load, and loaded a different one. I don't see any other choice than // to fail here. if (taskType != loadedType.Type) { logError ( taskLocation, taskLine, taskColumn, "ConflictingTaskAssembly", loadedType.Assembly.AssemblyFile, loadedType.Type.Assembly.Location ); taskInstanceInOtherAppDomain = null; } } else { taskInstanceInOtherAppDomain = (ITask)taskAppDomain.CreateInstanceAndUnwrap(loadedType.Type.Assembly.FullName, loadedType.Type.FullName); } return(taskInstanceInOtherAppDomain); } finally { // Don't leave appdomains open if (taskAppDomain != null && taskInstanceInOtherAppDomain == null) { AppDomain.Unload(taskAppDomain); RemoveAssemblyResolver(); } } }