/// <summary> /// Used to load information about default MSBuild tasks i.e. tasks that do not need to be explicitly declared in projects /// with the <UsingTask> element. Default task information is read from special files, which are located in the same /// directory as the MSBuild binaries. /// </summary> /// <remarks> /// 1) a default tasks file needs the <Project> root tag in order to be well-formed /// 2) the XML declaration tag <?xml ...> is ignored /// 3) comment tags are always ignored regardless of their placement /// 4) the rest of the tags are expected to be <UsingTask> tags /// </remarks> private void RegisterDefaultTasks(BuildEventContext buildEventContext) { if (!defaultTasksRegistrationAttempted) { try { this.defaultTaskRegistry = new TaskRegistry(); string[] defaultTasksFiles = { }; try { defaultTasksFiles = getFiles(toolset.ToolsPath, defaultTasksFilePattern); if (defaultTasksFiles.Length == 0) { loggingServices.LogWarning(buildEventContext, new BuildEventFileInfo(/* this warning truly does not involve any file */ String.Empty), "DefaultTasksFileLoadFailureWarning", defaultTasksFilePattern, toolset.ToolsPath, String.Empty); } } // handle security problems when finding the default tasks files catch (UnauthorizedAccessException e) { loggingServices.LogWarning(buildEventContext, new BuildEventFileInfo(/* this warning truly does not involve any file */ String.Empty), "DefaultTasksFileLoadFailureWarning", defaultTasksFilePattern, toolset.ToolsPath, e.Message); } // handle problems when reading the default tasks files catch (Exception e) // Catching Exception, but rethrowing unless it's an IO related exception. { if (ExceptionHandling.NotExpectedException(e)) { throw; } loggingServices.LogWarning(buildEventContext, new BuildEventFileInfo(/* this warning truly does not involve any file */ String.Empty), "DefaultTasksFileLoadFailureWarning", defaultTasksFilePattern, toolset.ToolsPath, e.Message); } BuildPropertyGroup propertyBag = null; foreach (string defaultTasksFile in defaultTasksFiles) { try { XmlDocument defaultTasks = loadXmlFromPath(defaultTasksFile); // look for the first root tag that is not a comment or an XML declaration -- this should be the <Project> tag // NOTE: the XML parser will guarantee there is only one real root element in the file // but we need to find it amongst the other types of XmlNode at the root. foreach (XmlNode topLevelNode in defaultTasks.ChildNodes) { if (XmlUtilities.IsXmlRootElement(topLevelNode)) { ProjectErrorUtilities.VerifyThrowInvalidProject(topLevelNode.LocalName == XMakeElements.project, topLevelNode, "UnrecognizedElement", topLevelNode.Name); ProjectErrorUtilities.VerifyThrowInvalidProject((topLevelNode.Prefix.Length == 0) && (String.Equals(topLevelNode.NamespaceURI, XMakeAttributes.defaultXmlNamespace, StringComparison.OrdinalIgnoreCase)), topLevelNode, "ProjectMustBeInMSBuildXmlNamespace", XMakeAttributes.defaultXmlNamespace); // the <Project> tag can only the XML namespace -- no other attributes foreach (XmlAttribute projectAttribute in topLevelNode.Attributes) { ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(projectAttribute.Name == XMakeAttributes.xmlns, projectAttribute); } // look at all the child tags of the <Project> root tag we found foreach (XmlNode usingTaskNode in topLevelNode.ChildNodes) { if (usingTaskNode.NodeType != XmlNodeType.Comment) { ProjectErrorUtilities.VerifyThrowInvalidProject(usingTaskNode.Name == XMakeElements.usingTask, usingTaskNode, "UnrecognizedElement", usingTaskNode.Name); // Initialize the property bag if it hasn't been already. if (propertyBag == null) { // Set the value of the MSBuildBinPath/ToolsPath properties. BuildPropertyGroup reservedPropertyBag = new BuildPropertyGroup(); reservedPropertyBag.SetProperty( new BuildProperty(ReservedPropertyNames.binPath, EscapingUtilities.Escape(toolset.ToolsPath), PropertyType.ReservedProperty)); reservedPropertyBag.SetProperty( new BuildProperty(ReservedPropertyNames.toolsPath, EscapingUtilities.Escape(toolset.ToolsPath), PropertyType.ReservedProperty)); // Also set MSBuildAssemblyVersion so that the tasks file can tell between v4 and v12 MSBuild reservedPropertyBag.SetProperty( new BuildProperty(ReservedPropertyNames.assemblyVersion, Constants.AssemblyVersion, PropertyType.ReservedProperty)); propertyBag = new BuildPropertyGroup(); propertyBag.ImportInitialProperties(parentEngine.EnvironmentProperties, reservedPropertyBag, BuildProperties, parentEngine.GlobalProperties); } defaultTaskRegistry.RegisterTask(new UsingTask((XmlElement)usingTaskNode, true), new Expander(propertyBag), loggingServices, buildEventContext); } } break; } } } // handle security problems when loading the default tasks file catch (UnauthorizedAccessException e) { loggingServices.LogError(buildEventContext, new BuildEventFileInfo(defaultTasksFile), "DefaultTasksFileFailure", e.Message); break; } // handle problems when loading the default tasks file catch (IOException e) { loggingServices.LogError(buildEventContext, new BuildEventFileInfo(defaultTasksFile), "DefaultTasksFileFailure", e.Message); break; } // handle XML errors in the default tasks file catch (XmlException e) { ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(false, new BuildEventFileInfo(e), "DefaultTasksFileFailure", e.Message); } } } finally { defaultTasksRegistrationAttempted = true; } } }
internal BuildItemGroupChildXml(XmlElement element, ChildType childTypeExpected) { ErrorUtilities.VerifyThrow(element != null, "Need an XML node."); ErrorUtilities.VerifyThrowNoAssert(childTypeExpected != ChildType.Invalid, "Can't expect invalid childtype"); ProjectXmlUtilities.VerifyThrowProjectValidNameAndNamespace(element); this.element = element; // Loop through each of the attributes on the item element. foreach (XmlAttribute attribute in element.Attributes) { switch (attribute.Name) { case XMakeAttributes.include: this.includeAttribute = attribute; break; case XMakeAttributes.exclude: this.excludeAttribute = attribute; break; case XMakeAttributes.condition: this.conditionAttribute = attribute; break; case XMakeAttributes.xmlns: // We already verified that the namespace is correct break; case XMakeAttributes.remove: this.removeAttribute = attribute; break; case XMakeAttributes.keepMetadata: case XMakeAttributes.removeMetadata: case XMakeAttributes.keepDuplicates: // Ignore these - they are part of the new OM. break; default: ProjectXmlUtilities.ThrowProjectInvalidAttribute(attribute); break; } } this.childType = ChildType.Invalid; // Default to modify, if that's one of the child types we are told to expect. if ((childTypeExpected & ChildType.BuildItemModify) == ChildType.BuildItemModify) { this.childType = ChildType.BuildItemModify; } if (this.includeAttribute != null) { ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((childTypeExpected & ChildType.BuildItemAdd) == ChildType.BuildItemAdd, includeAttribute); ProjectErrorUtilities.VerifyThrowInvalidProject(Include.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.include, element.Name); ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(removeAttribute == null, removeAttribute); this.childType = ChildType.BuildItemAdd; } if (this.excludeAttribute != null) { ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((childTypeExpected & ChildType.BuildItemAdd) == ChildType.BuildItemAdd, excludeAttribute); ProjectErrorUtilities.VerifyThrowInvalidProject(Include.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.include, element.Name); ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(removeAttribute == null, removeAttribute); this.childType = ChildType.BuildItemAdd; } if (this.removeAttribute != null) { ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((childTypeExpected & ChildType.BuildItemRemove) == ChildType.BuildItemRemove, removeAttribute); ProjectErrorUtilities.VerifyThrowInvalidProject(Remove.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.remove, element.Name); ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(includeAttribute == null, includeAttribute); ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(excludeAttribute == null, excludeAttribute); this.childType = ChildType.BuildItemRemove; } if (this.childType == ChildType.Invalid) { // So the xml wasn't consistent with any of the child types that we were told to expect. // Figure out the most reasonable message to produce. if ((childTypeExpected & ChildType.BuildItemAdd) == ChildType.BuildItemAdd) { ProjectErrorUtilities.VerifyThrowInvalidProject(Include.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.include, element.Name); } else if ((childTypeExpected & ChildType.BuildItemRemove) == ChildType.BuildItemRemove) { ProjectErrorUtilities.VerifyThrowInvalidProject(Remove.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.remove, element.Name); } else { ErrorUtilities.ThrowInternalError("Unexpected child type"); } } // Validate each of the child nodes beneath the item. List <XmlElement> children = ProjectXmlUtilities.GetValidChildElements(element); if (this.childType == ChildType.BuildItemRemove && children.Count != 0) { ProjectErrorUtilities.ThrowInvalidProject(element, "ChildElementsBelowRemoveNotAllowed", children[0].Name); } foreach (XmlElement child in children) { ProjectXmlUtilities.VerifyThrowProjectValidNameAndNamespace(child); ProjectErrorUtilities.VerifyThrowInvalidProject(!FileUtilities.IsItemSpecModifier(child.Name), child, "ItemSpecModifierCannotBeCustomMetadata", child.Name); ProjectErrorUtilities.VerifyThrowInvalidProject(XMakeElements.IllegalItemPropertyNames[child.Name] == null, child, "CannotModifyReservedItemMetadata", child.Name); } }