예제 #1
0
        /// <summary>
        /// Cleans up after running the task.
        /// </summary>
        void ITaskExecutionHost.CleanupForTask()
        {
            if (_resolver != null)
            {
                _resolver.RemoveHandler();
                _resolver = null;
            }

            _taskFactoryWrapper = null;

            // We must null this out because it could be a COM object (or any other ref-counted object) which needs to
            // be released.
            _taskHost = null;
            CleanupCancellationToken();

            ErrorUtilities.VerifyThrow(_taskInstance == null, "Task Instance should be null");
        }
예제 #2
0
        /// <summary>
        /// Given the task name, this method tries to find the task. It uses the following search order:
        /// 1) checks the tasks declared by the project, searching by exact name and task identity parameters
        /// 2) checks the global task declarations (in *.TASKS in MSbuild bin dir), searching by exact name and task identity parameters
        /// 3) checks the tasks declared by the project, searching by fuzzy match (missing namespace, etc.) and task identity parameters
        /// 4) checks the global task declarations (in *.TASKS in MSbuild bin dir), searching by fuzzy match (missing namespace, etc.) and task identity parameters
        /// 5) 1-4 again in order without the task identity parameters, to gather additional information for the user (if the task identity 
        ///    parameters don't match, it is an error, but at least we can return them a more useful error in this case than just "could not 
        ///    find task")
        /// 
        /// The search ordering is meant to reduce the number of assemblies we scan, because loading assemblies can be expensive.
        /// The tasks and assemblies declared by the project are scanned first, on the assumption that if the project declared
        /// them, they are likely used.
        /// 
        /// If the set of task identity parameters are defined, only tasks that match that identity are chosen. 
        /// </summary>
        /// <returns>The Type of the task, or null if it was not found.</returns>
        private TaskFactoryWrapper FindTaskInRegistry(IDictionary<string, string> taskIdentityParameters)
        {
            TaskFactoryWrapper returnClass;
            if (!_intrinsicTasks.TryGetValue(_taskName, out returnClass))
            {
                returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, taskIdentityParameters, true /* exact match */, _targetLoggingContext, _taskLocation);
                if (null == returnClass)
                {
                    returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, taskIdentityParameters, false /* fuzzy match */, _targetLoggingContext, _taskLocation);

                    if (null == returnClass)
                    {
                        returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, null, true /* exact match */, _targetLoggingContext, _taskLocation);

                        if (null == returnClass)
                        {
                            returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, null, false /* fuzzy match */, _targetLoggingContext, _taskLocation);

                            if (null == returnClass)
                            {
                                _targetLoggingContext.LogError
                                    (
                                        new BuildEventFileInfo(_taskLocation),
                                        "MissingTaskError",
                                        _taskName,
                                        _projectInstance.TaskRegistry.Toolset.ToolsPath
                                    );

                                return returnClass;
                            }
                        }

                        string usingTaskRuntime = null;
                        string usingTaskArchitecture = null;
                        string taskRuntime = null;
                        string taskArchitecture = null;

                        if (returnClass.FactoryIdentityParameters != null)
                        {
                            returnClass.FactoryIdentityParameters.TryGetValue(XMakeAttributes.runtime, out usingTaskRuntime);
                            returnClass.FactoryIdentityParameters.TryGetValue(XMakeAttributes.architecture, out usingTaskArchitecture);
                        }

                        taskIdentityParameters.TryGetValue(XMakeAttributes.runtime, out taskRuntime);
                        taskIdentityParameters.TryGetValue(XMakeAttributes.architecture, out taskArchitecture);

                        _targetLoggingContext.LogError
                            (
                                new BuildEventFileInfo(_taskLocation),
                                "TaskExistsButHasMismatchedIdentityError",
                                _taskName,
                                usingTaskRuntime ?? XMakeAttributes.MSBuildRuntimeValues.any,
                                usingTaskArchitecture ?? XMakeAttributes.MSBuildArchitectureValues.any,
                                taskRuntime ?? XMakeAttributes.MSBuildRuntimeValues.any,
                                taskArchitecture ?? XMakeAttributes.MSBuildArchitectureValues.any
                            );

                        // if we've logged this error, even though we've found something, we want to act like we didn't.  
                        return null;
                    }
                }

                if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDDISABLEINTRINSICMSBUILDTASK")))
                {
                    // Map to an intrinsic task, if necessary.
                    if (String.Equals(returnClass.TaskFactory.TaskType.FullName, "Microsoft.Build.Tasks.MSBuild", StringComparison.OrdinalIgnoreCase))
                    {
                        returnClass = new TaskFactoryWrapper(new IntrinsicTaskFactory(typeof(MSBuild)), new LoadedType(typeof(MSBuild), AssemblyLoadInfo.Create(Assembly.GetExecutingAssembly().FullName, null)), _taskName, null);
                        _intrinsicTasks[_taskName] = returnClass;
                    }
                    else if (String.Equals(returnClass.TaskFactory.TaskType.FullName, "Microsoft.Build.Tasks.CallTarget", StringComparison.OrdinalIgnoreCase))
                    {
                        returnClass = new TaskFactoryWrapper(new IntrinsicTaskFactory(typeof(CallTarget)), new LoadedType(typeof(CallTarget), AssemblyLoadInfo.Create(Assembly.GetExecutingAssembly().FullName, null)), _taskName, null);
                        _intrinsicTasks[_taskName] = returnClass;
                    }
                }
            }

            return returnClass;
        }
예제 #3
0
        /// <summary>
        /// Ask the task host to find its task in the registry and get it ready for initializing the batch
        /// </summary>
        /// <returns>True if the task is found in the task registry false if otherwise.</returns>
        TaskRequirements? ITaskExecutionHost.FindTask(IDictionary<string, string> taskIdentityParameters)
        {
            if (_taskFactoryWrapper == null)
            {
                _taskFactoryWrapper = FindTaskInRegistry(taskIdentityParameters);
            }

            if (_taskFactoryWrapper == null)
            {
                return null;
            }

            TaskRequirements requirements = TaskRequirements.None;

            if (_taskFactoryWrapper.TaskFactoryLoadedType.HasSTAThreadAttribute())
            {
                requirements = requirements | TaskRequirements.RequireSTAThread;
            }

            if (_taskFactoryWrapper.TaskFactoryLoadedType.HasLoadInSeparateAppDomainAttribute())
            {
                requirements = requirements | TaskRequirements.RequireSeparateAppDomain;

                // we're going to be remoting across the appdomain boundary, so
                // create the list that we'll use to disconnect the taskitems once we're done
                _remotedTaskItems = new List<TaskItem>();
            }

            return requirements;
        }