/// <summary> /// Log errors from TaskLoader. /// </summary> private void ErrorLoggingDelegate(string taskLocation, int taskLine, int taskColumn, string message, params object[] messageArgs) { _taskLoggingContext.LogError(new BuildEventFileInfo(taskLocation, taskLine, taskColumn), message, messageArgs); }
/// <summary> /// Create an instance of the wrapped ITask for a batch run of the task. /// </summary> public ITask CreateTaskInstance(ElementLocation taskLocation, TaskLoggingContext taskLoggingContext, AppDomainSetup appDomainSetup, bool isOutOfProc) { separateAppDomain = false; separateAppDomain = loadedType.HasLoadInSeparateAppDomainAttribute(); taskAppDomain = null; if (separateAppDomain) { if (!loadedType.Type.IsMarshalByRef) { taskLoggingContext.LogError ( new BuildEventFileInfo(taskLocation), "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); taskAppDomain = AppDomain.CreateDomain(isOutOfProc ? "taskAppDomain (out-of-proc)" : "taskAppDomain (in-proc)", null, appDomainInfo); // Hook up last minute dumping of any exceptions taskAppDomain.UnhandledException += new UnhandledExceptionEventHandler(ExceptionHandling.UnhandledExceptionHandler); } } // instantiate the task in given domain if (taskAppDomain == null || taskAppDomain == AppDomain.CurrentDomain) { // 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. taskInstance = (ITask)Activator.CreateInstance(loadedType.Type); return taskInstance; } if (loadedType.Assembly.AssemblyFile != null) { taskInstance = (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 = taskInstance.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) { taskLoggingContext.LogError ( new BuildEventFileInfo(taskLocation), "ConflictingTaskAssembly", loadedType.Assembly.AssemblyFile, loadedType.Type.Assembly.Location ); taskInstance = null; } } else { taskInstance = (ITask)taskAppDomain.CreateInstanceAndUnwrap(loadedType.Type.Assembly.FullName, loadedType.Type.FullName); } return taskInstance; }