Exemple #1
0
 /// <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;
        }