예제 #1
0
        /// <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();
                }
            }
        }
예제 #2
0
        /// <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
            }
        }
예제 #3
0
        /// <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();
                }
            }
        }