/// <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"); }
/// <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; }
/// <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; }