void StdOutCallback(object sender, DataReceivedEventArgs e) { if (e.Data != null) { log.LogMessageFromText(e.Data, MessageImportance.High); } }
public void WriteLine(string line) { bool logAsError = false; string rawLine = line; InfoMessages.Add(line); RemoveCmakePrefix(); FormatLinkerPrefix(); // output format of librarybuilder does not match visual studio error format string libBuilder = "[EngineeringLibraryBuilder]:"; if (line.TrimStart().StartsWith(libBuilder) && ErrorMessages.Contains(line)) { logAsError = true; } if (logAsError) { _loggingHelper.LogMessageFromText("error: " + line, MessageImportance.High); } else { _loggingHelper.LogMessageFromText(line, MessageImportance.Normal); } void RemoveCmakePrefix() { string cmake = "[cmake]: "; if (line.Contains(cmake)) { line = line.Substring(line.IndexOf(cmake) + cmake.Length); } } void FormatLinkerPrefix() { string linker = "real-ld.exe"; if (line.Contains(linker + ":")) { string linkerPath = line.Substring(0, line.IndexOf(linker) + linker.Length); if (File.Exists(linkerPath)) { if (ErrorMessages.Contains(rawLine)) { logAsError = true; } line = line.Substring(line.IndexOf(linker) + linker.Length + 1) + $"(message from {linkerPath})"; } } } }
internal static bool GetTableWithEscaping(TaskLoggingHelper log, string parameterName, string syntaxName, string[] propertyNameValueStrings, out Hashtable finalPropertiesTable) { finalPropertiesTable = null; if (propertyNameValueStrings != null) { finalPropertiesTable = new Hashtable(StringComparer.OrdinalIgnoreCase); List <PropertyNameValuePair> list = new List <PropertyNameValuePair>(); foreach (string str in propertyNameValueStrings) { int index = str.IndexOf('='); if (index != -1) { string propertyName = str.Substring(0, index).Trim(); string propertyValue = Microsoft.Build.Shared.EscapingUtilities.Escape(str.Substring(index + 1).Trim()); if (propertyName.Length == 0) { if (log != null) { log.LogErrorWithCodeFromResources("General.InvalidPropertyError", new object[] { syntaxName, str }); } return(false); } list.Add(new PropertyNameValuePair(propertyName, propertyValue)); } else if (list.Count > 0) { string str4 = Microsoft.Build.Shared.EscapingUtilities.Escape(str.Trim()); list[list.Count - 1].Value.Append(';'); list[list.Count - 1].Value.Append(str4); } else { if (log != null) { log.LogErrorWithCodeFromResources("General.InvalidPropertyError", new object[] { syntaxName, str }); } return(false); } } if (log != null) { log.LogMessageFromText(parameterName, MessageImportance.Low); } foreach (PropertyNameValuePair pair in list) { finalPropertiesTable[pair.Name] = pair.Value.ToString(); if (log != null) { log.LogMessageFromText(string.Format(CultureInfo.InvariantCulture, " {0}={1}", new object[] { pair.Name, pair.Value.ToString() }), MessageImportance.Low); } } } return(true); }
public bool Execute() { // set up support for logging TaskLoggingHelper loggingHelper = new TaskLoggingHelper(this); // Log Variables loggingHelper.LogMessageFromText("Custom Task QueueBuild Starting", MessageImportance.High); loggingHelper.LogMessageFromText("tfsServer = " + tfsServer, MessageImportance.High); loggingHelper.LogMessageFromText("teamProject = " + teamProject, MessageImportance.High); loggingHelper.LogMessageFromText("buildDefinition = " + buildDefinition, MessageImportance.High); // Get the team foundation server TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(tfsServer); // Get the IBuildServer IBuildServer buildServer = (IBuildServer)tfs.GetService(typeof(IBuildServer)); // Get the build definition for which a build is to be queued IBuildDefinition buildDef = buildServer.GetBuildDefinition(teamProject, buildDefinition); // Create variable for queuedBuild and queue the build var queuedBuild = buildServer.QueueBuild(buildDef); loggingHelper.LogMessageFromText("Waiting for newly queued build from Team Project : " + teamProject + " : and Build Definition : " + buildDefinition + " : to complete", MessageImportance.High); loggingHelper.LogMessageFromText("Pinging queuedBuild : " + queuedBuild + " : every 5 seconds to confirm when build is complete", MessageImportance.High); // Wait for the completion of newly queued build - Will ping build every 5 seconds to confirm completion for a max of 5 hours queuedBuild.WaitForBuildCompletion(TimeSpan.FromSeconds(5), TimeSpan.FromHours(5)); loggingHelper.LogMessageFromText("Queued Build : " + queuedBuild.Build.BuildNumber + " has now completed", MessageImportance.High); loggingHelper.LogMessageFromText("Returning to original build", MessageImportance.High); return(true); }
public override bool Execute() { TaskLoggingHelper loggingHelper = new TaskLoggingHelper(this); try { loggingHelper.LogMessageFromText("*** Start View Model generation from Proto Reflection", MessageImportance.High); if (SourceFiles.Count() != DestinationFiles.Count()) { loggingHelper.LogError("Expected SourceFiles.Count == DestinationFiles.Count"); return(false); } int count = SourceFiles.Count(); if (count == 0) { loggingHelper.LogError("Expected SourceFiles.Count > 0"); return(false); } for (int i = 0; i < count; i++) { Generate(SourceFiles[i], DestinationFiles[i], loggingHelper); } } catch (Exception ex) { loggingHelper.LogErrorFromException(ex); return(false); } return(true); }
private void EmbedAssemblies(ICollection <EmbeddedItemInfo> itemsToEmbed) { var targetAssemblyPath = _targetsPath[0].GetFullPath(); WriterParameters writerParameters = null; var assembly = ReadAssembly(targetAssemblyPath, out writerParameters); foreach (var item in itemsToEmbed) { var message = String.Format("Embedding \"{0}\"", item.Path); _log.LogMessageFromText(message, MessageImportance.Normal); var data = File.ReadAllBytes(item.Path); var resource = new EmbeddedResource(item.Name, ManifestResourceAttributes.Private, data); assembly.MainModule.Resources.Add(resource); } var injector = new CodeInjector(assembly); injector.Inject(); //if (!String.IsNullOrEmpty(_keyFile) && File.Exists(_keyFile)) //{ // writerParameters.StrongNameKeyPair = new System.Reflection.StrongNameKeyPair(_keyFile); // var pb = writerParameters.StrongNameKeyPair.PublicKey; //} assembly.Write(targetAssemblyPath, writerParameters); }
public bool Execute() { //set up support for logging TaskLoggingHelper loggingHelper = new TaskLoggingHelper(this); loggingHelper.LogMessageFromText( "Hello MSBuild", MessageImportance.High); return(true); }
void StdOutCallback(object sender, DataReceivedEventArgs e) { if (e.Data != null) { if (String.Compare(e.Data, 0, "Opening file", 0, 12) == 0 || String.Compare(e.Data, 0, "Current working dir", 0, 19) == 0) { return; } else if (String.Compare(e.Data, 0, "Resolved to", 0, 11) == 0) { String filename = e.Data.Substring(13, e.Data.Length - 14); depends.AddDependency(cmdline.SourceFile, filename); } else { log.LogMessageFromText(e.Data, MessageImportance.High); } } }
public void LogMessage(Mono.Linker.MessageImportance importance, string message, params object[] values) { Microsoft.Build.Framework.MessageImportance msBuildImportance; switch (importance) { case Mono.Linker.MessageImportance.High: msBuildImportance = MessageImportance.High; break; case Mono.Linker.MessageImportance.Normal: msBuildImportance = MessageImportance.Normal; break; case Mono.Linker.MessageImportance.Low: msBuildImportance = MessageImportance.Low; break; default: throw new ArgumentException($"Unrecognized importance level {importance}", nameof(importance)); } log.LogMessageFromText(String.Format(message, values), msBuildImportance); }
/// <returns>True if the operation was successful</returns> internal static bool ExecuteTargets ( List <ITaskItem> projects, Dictionary <string, string> propertiesTable, string[] undefineProperties, List <string[]> targetLists, bool stopOnFirstFailure, bool rebaseOutputs, IBuildEngine3 buildEngine, TaskLoggingHelper log, List <ITaskItem> targetOutputs, bool unloadProjectsOnCompletion, string toolsVersion ) { bool success = true; // We don't log a message about the project and targets we're going to // build, because it'll all be in the immediately subsequent ProjectStarted event. var projectDirectory = new string[projects.Count]; var projectNames = new string[projects.Count]; var toolsVersions = new string[projects.Count]; var projectProperties = new Dictionary <string, string> [projects.Count]; var undefinePropertiesPerProject = new IList <string> [projects.Count]; for (int i = 0; i < projectNames.Length; i++) { projectNames[i] = null; projectProperties[i] = propertiesTable; if (projects[i] != null) { // Retrieve projectDirectory only the first time. It never changes anyway. string projectPath = FileUtilities.AttemptToShortenPath(projects[i].ItemSpec); projectDirectory[i] = Path.GetDirectoryName(projectPath); projectNames[i] = projects[i].ItemSpec; toolsVersions[i] = toolsVersion; // If the user specified a different set of global properties for this project, then // parse the string containing the properties if (!String.IsNullOrEmpty(projects[i].GetMetadata("Properties"))) { if (!PropertyParser.GetTableWithEscaping (log, ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("General.OverridingProperties", projectNames[i]), "Properties", projects[i].GetMetadata("Properties").Split(MSBuildConstants.SemicolonChar), out Dictionary <string, string> preProjectPropertiesTable) ) { return(false); } projectProperties[i] = preProjectPropertiesTable; } if (undefineProperties != null) { undefinePropertiesPerProject[i] = new List <string>(undefineProperties); } // If the user wanted to undefine specific global properties for this project, parse // that string and remove them now. string projectUndefineProperties = projects[i].GetMetadata("UndefineProperties"); if (!String.IsNullOrEmpty(projectUndefineProperties)) { string[] propertiesToUndefine = projectUndefineProperties.Split(MSBuildConstants.SemicolonChar); if (undefinePropertiesPerProject[i] == null) { undefinePropertiesPerProject[i] = new List <string>(propertiesToUndefine.Length); } if (log != null && propertiesToUndefine.Length > 0) { log.LogMessageFromResources(MessageImportance.Low, "General.ProjectUndefineProperties", projectNames[i]); foreach (string property in propertiesToUndefine) { undefinePropertiesPerProject[i].Add(property); log.LogMessageFromText($" {property}", MessageImportance.Low); } } } // If the user specified a different set of global properties for this project, then // parse the string containing the properties if (!String.IsNullOrEmpty(projects[i].GetMetadata("AdditionalProperties"))) { if (!PropertyParser.GetTableWithEscaping (log, ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("General.AdditionalProperties", projectNames[i]), "AdditionalProperties", projects[i].GetMetadata("AdditionalProperties").Split(MSBuildConstants.SemicolonChar), out Dictionary <string, string> additionalProjectPropertiesTable) ) { return(false); } var combinedTable = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); // First copy in the properties from the global table that not in the additional properties table if (projectProperties[i] != null) { foreach (KeyValuePair <string, string> entry in projectProperties[i]) { if (!additionalProjectPropertiesTable.ContainsKey(entry.Key)) { combinedTable.Add(entry.Key, entry.Value); } } } // Add all the additional properties foreach (KeyValuePair <string, string> entry in additionalProjectPropertiesTable) { combinedTable.Add(entry.Key, entry.Value); } projectProperties[i] = combinedTable; } // If the user specified a different toolsVersion for this project - then override the setting if (!String.IsNullOrEmpty(projects[i].GetMetadata("ToolsVersion"))) { toolsVersions[i] = projects[i].GetMetadata("ToolsVersion"); } } } foreach (string[] targetList in targetLists) { if (stopOnFirstFailure && !success) { // Inform the user that we skipped the remaining targets StopOnFirstFailure=true. log.LogMessageFromResources(MessageImportance.Low, "MSBuild.SkippingRemainingTargets"); // We have encountered a failure. Caller has requested that we not // continue with remaining targets. break; } // Send the project off to the build engine. By passing in null to the // first param, we are indicating that the project to build is the same // as the *calling* project file. BuildEngineResult result = buildEngine.BuildProjectFilesInParallel(projectNames, targetList, projectProperties, undefinePropertiesPerProject, toolsVersions, true /* ask that target outputs are returned in the buildengineresult */); bool currentTargetResult = result.Result; IList <IDictionary <string, ITaskItem[]> > targetOutputsPerProject = result.TargetOutputsPerProject; success = success && currentTargetResult; // If the engine was able to satisfy the build request if (currentTargetResult) { for (int i = 0; i < projects.Count; i++) { IEnumerable <string> nonNullTargetList = targetList ?? targetOutputsPerProject[i].Keys; foreach (string targetName in nonNullTargetList) { if (targetOutputsPerProject[i].TryGetValue(targetName, out ITaskItem[] outputItemsFromTarget))
void _logLine(string line) { _log.LogMessageFromText(line, MessageImportance.High); }
/// <summary> /// /// </summary> /// <returns>True if the operation was successful</returns> internal static async Task<bool> ExecuteTargets ( ITaskItem[] projects, Hashtable propertiesTable, string[] undefineProperties, ArrayList targetLists, bool stopOnFirstFailure, bool rebaseOutputs, IBuildEngine3 buildEngine, TaskLoggingHelper log, ArrayList targetOutputs, bool useResultsCache, bool unloadProjectsOnCompletion, string toolsVersion ) { bool success = true; // We don't log a message about the project and targets we're going to // build, because it'll all be in the immediately subsequent ProjectStarted event. string[] projectDirectory = new string[projects.Length]; string[] projectNames = new string[projects.Length]; string[] toolsVersions = new string[projects.Length]; IList<IDictionary<string, ITaskItem[]>> targetOutputsPerProject = null; IDictionary[] projectProperties = new IDictionary[projects.Length]; List<string>[] undefinePropertiesPerProject = new List<string>[projects.Length]; for (int i = 0; i < projectNames.Length; i++) { projectNames[i] = null; projectProperties[i] = propertiesTable; if (projects[i] != null) { // Retrieve projectDirectory only the first time. It never changes anyway. string projectPath = FileUtilities.AttemptToShortenPath(projects[i].ItemSpec); projectDirectory[i] = Path.GetDirectoryName(projectPath); projectNames[i] = projects[i].ItemSpec; toolsVersions[i] = toolsVersion; // If the user specified a different set of global properties for this project, then // parse the string containing the properties if (!String.IsNullOrEmpty(projects[i].GetMetadata("Properties"))) { Hashtable preProjectPropertiesTable; if (!PropertyParser.GetTableWithEscaping (log, ResourceUtilities.FormatResourceString("General.OverridingProperties", projectNames[i]), "Properties", projects[i].GetMetadata("Properties").Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries), out preProjectPropertiesTable) ) { return false; } projectProperties[i] = preProjectPropertiesTable; } if (undefineProperties != null) { undefinePropertiesPerProject[i] = new List<string>(undefineProperties); } // If the user wanted to undefine specific global properties for this project, parse // that string and remove them now. string projectUndefineProperties = projects[i].GetMetadata("UndefineProperties"); if (!String.IsNullOrEmpty(projectUndefineProperties)) { string[] propertiesToUndefine = projectUndefineProperties.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); if (undefinePropertiesPerProject[i] == null) { undefinePropertiesPerProject[i] = new List<string>(propertiesToUndefine.Length); } if (log != null && propertiesToUndefine.Length > 0) { log.LogMessageFromResources(MessageImportance.Low, "General.ProjectUndefineProperties", projectNames[i]); foreach (string property in propertiesToUndefine) { undefinePropertiesPerProject[i].Add(property); log.LogMessageFromText(String.Format(CultureInfo.InvariantCulture, " {0}", property), MessageImportance.Low); } } } // If the user specified a different set of global properties for this project, then // parse the string containing the properties if (!String.IsNullOrEmpty(projects[i].GetMetadata("AdditionalProperties"))) { Hashtable additionalProjectPropertiesTable; if (!PropertyParser.GetTableWithEscaping (log, ResourceUtilities.FormatResourceString("General.AdditionalProperties", projectNames[i]), "AdditionalProperties", projects[i].GetMetadata("AdditionalProperties").Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries), out additionalProjectPropertiesTable) ) { return false; } Hashtable combinedTable = new Hashtable(StringComparer.OrdinalIgnoreCase); // First copy in the properties from the global table that not in the additional properties table if (projectProperties[i] != null) { foreach (DictionaryEntry entry in projectProperties[i]) { if (!additionalProjectPropertiesTable.Contains(entry.Key)) { combinedTable.Add(entry.Key, entry.Value); } } } // Add all the additional properties foreach (DictionaryEntry entry in additionalProjectPropertiesTable) { combinedTable.Add(entry.Key, entry.Value); } projectProperties[i] = combinedTable; } // If the user specified a different toolsVersion for this project - then override the setting if (!String.IsNullOrEmpty(projects[i].GetMetadata("ToolsVersion"))) { toolsVersions[i] = projects[i].GetMetadata("ToolsVersion"); } } } foreach (string[] targetList in targetLists) { if (stopOnFirstFailure && !success) { // Inform the user that we skipped the remaining targets StopOnFirstFailure=true. log.LogMessageFromResources(MessageImportance.Low, "MSBuild.SkippingRemainingTargets"); // We have encountered a failure. Caller has requested that we not // continue with remaining targets. break; } // Send the project off to the build engine. By passing in null to the // first param, we are indicating that the project to build is the same // as the *calling* project file. bool currentTargetResult = true; TaskHost taskHost = (TaskHost)buildEngine; BuildEngineResult result = await taskHost.InternalBuildProjects(projectNames, targetList, projectProperties, undefinePropertiesPerProject, toolsVersions, true /* ask that target outputs are returned in the buildengineresult */); currentTargetResult = result.Result; targetOutputsPerProject = result.TargetOutputsPerProject; success = success && currentTargetResult; // If the engine was able to satisfy the build request if (currentTargetResult) { for (int i = 0; i < projects.Length; i++) { IEnumerable nonNullTargetList = (targetList != null) ? targetList : targetOutputsPerProject[i].Keys; foreach (string targetName in nonNullTargetList) { if (targetOutputsPerProject[i].ContainsKey(targetName)) { ITaskItem[] outputItemsFromTarget = (ITaskItem[])targetOutputsPerProject[i][targetName]; foreach (ITaskItem outputItemFromTarget in outputItemsFromTarget) { // No need to rebase if the calling project is the same as the callee project // (project == null). Also no point in trying to copy item metadata either, // because no items were passed into the Projects parameter! if (projects[i] != null) { // Rebase the output item paths if necessary. No need to rebase if the calling // project is the same as the callee project (project == null). if (rebaseOutputs) { try { outputItemFromTarget.ItemSpec = Path.Combine(projectDirectory[i], outputItemFromTarget.ItemSpec); } catch (ArgumentException e) { log.LogWarningWithCodeFromResources(null, projects[i].ItemSpec, 0, 0, 0, 0, "MSBuild.CannotRebaseOutputItemPath", outputItemFromTarget.ItemSpec, e.Message); } } // Copy the custom item metadata from the "Projects" items to these // output items. projects[i].CopyMetadataTo(outputItemFromTarget); // Set a metadata on the output items called "MSBuildProjectFile" which tells you which project file produced this item. if (String.IsNullOrEmpty(outputItemFromTarget.GetMetadata(ItemMetadataNames.msbuildSourceProjectFile))) { outputItemFromTarget.SetMetadata(ItemMetadataNames.msbuildSourceProjectFile, projects[i].GetMetadata(FileUtilities.ItemSpecModifiers.FullPath)); } } // Set a metadata on the output items called "MSBuildTargetName" which tells you which target produced this item. if (String.IsNullOrEmpty(outputItemFromTarget.GetMetadata(ItemMetadataNames.msbuildSourceTargetName))) { outputItemFromTarget.SetMetadata(ItemMetadataNames.msbuildSourceTargetName, targetName); } } targetOutputs.AddRange(outputItemsFromTarget); } } } } } return success; }
/// <summary> /// Given a string of semi-colon delimited name=value pairs, this method parses it and creates /// a hash table containing the property names as keys and the property values as values. /// This method escapes any special characters found in the property values, in case they /// are going to be passed to a method (such as that expects the appropriate escaping to have happened /// already. /// </summary> /// <param name="log"></param> /// <param name="propertyList"></param> /// <param name="propertiesTable"></param> /// <returns>true on success, false on failure.</returns> static internal bool GetTableWithEscaping(TaskLoggingHelper log, string parameterName, string syntaxName, string[] propertyNameValueStrings, out Hashtable finalPropertiesTable) { finalPropertiesTable = null; if (propertyNameValueStrings != null) { finalPropertiesTable = new Hashtable(StringComparer.OrdinalIgnoreCase); List<PropertyNameValuePair> finalPropertiesList = new List<PropertyNameValuePair>(); // Loop through the array. Each string in the array should be of the form: // MyPropName=MyPropValue foreach (string propertyNameValueString in propertyNameValueStrings) { // Find the first '=' sign in the string. int indexOfEqualsSign = propertyNameValueString.IndexOf('='); if (indexOfEqualsSign != -1) { // If we found one, then grab the stuff before it and put it into "propertyName", // and grab the stuff after it and put it into "propertyValue". But trim the // whitespace from beginning and end of both name and value. (When authoring a // project/targets file, people like to use whitespace and newlines to pretty up // the file format.) string propertyName = propertyNameValueString.Substring(0, indexOfEqualsSign).Trim(); string propertyValue = EscapingUtilities.Escape(propertyNameValueString.Substring(indexOfEqualsSign + 1).Trim()); // Make sure we have a property name and property value (though the value is allowed to be blank). if (propertyName.Length == 0) { // No property name? That's no good to us. if (log != null) { log.LogErrorWithCodeFromResources("General.InvalidPropertyError", syntaxName, propertyNameValueString); } return false; } // Store the property in our list. finalPropertiesList.Add(new PropertyNameValuePair(propertyName, propertyValue)); } else { // There's no '=' sign in the string. When this happens, we treat this string as basically // an appendage on the value of the previous property. For example, if the project file contains // // <PropertyGroup> // <WarningsAsErrors>1234;5678;9999</WarningsAsErrors> // </PropertyGroup> // <Target Name="Build"> // <MSBuild Projects="ConsoleApplication1.csproj" // Properties="WarningsAsErrors=$(WarningsAsErrors)"/> // </Target> // // , then this method (GetTableWithEscaping) will see this: // // propertyNameValueStrings[0] = "WarningsAsErrors=1234" // propertyNameValueStrings[1] = "5678" // propertyNameValueStrings[2] = "9999" // // And what we actually want to end up with in our final hashtable is this: // // NAME VALUE // =================== ================================ // WarningsAsErrors 1234;5678;9999 // if (finalPropertiesList.Count > 0) { // There was a property definition previous to this one. Append the current string // to that previous value, using semicolon as a separator. string propertyValue = EscapingUtilities.Escape(propertyNameValueString.Trim()); finalPropertiesList[finalPropertiesList.Count - 1].Value.Append(';'); finalPropertiesList[finalPropertiesList.Count - 1].Value.Append(propertyValue); } else { // No equals sign in the very first property? That's a problem. if (log != null) { log.LogErrorWithCodeFromResources("General.InvalidPropertyError", syntaxName, propertyNameValueString); } return false; } } } // Convert the data in the List to a Hashtable, because that's what the MSBuild task eventually // needs to pass onto the engine. if (log != null) { log.LogMessageFromText(parameterName, MessageImportance.Low); } foreach (PropertyNameValuePair propertyNameValuePair in finalPropertiesList) { string propertyValue = OpportunisticIntern.StringBuilderToString(propertyNameValuePair.Value); finalPropertiesTable[propertyNameValuePair.Name] = propertyValue; if (log != null) { log.LogMessageFromText(String.Format(CultureInfo.InvariantCulture, " {0}={1}", propertyNameValuePair.Name, propertyValue), MessageImportance.Low); } } } return true; }
internal static bool ExecuteTargets(ITaskItem[] projects, Hashtable propertiesTable, string[] undefineProperties, ArrayList targetLists, bool stopOnFirstFailure, bool rebaseOutputs, IBuildEngine3 buildEngine, TaskLoggingHelper log, ArrayList targetOutputs, bool useResultsCache, bool unloadProjectsOnCompletion, string toolsVersion) { bool flag = true; string[] strArray = new string[projects.Length]; string[] projectFileNames = new string[projects.Length]; string[] strArray3 = new string[projects.Length]; IList <IDictionary <string, ITaskItem[]> > targetOutputsPerProject = null; IDictionary[] globalProperties = new IDictionary[projects.Length]; List <string>[] removeGlobalProperties = new List <string> [projects.Length]; for (int i = 0; i < projectFileNames.Length; i++) { projectFileNames[i] = null; globalProperties[i] = propertiesTable; if (projects[i] != null) { string path = Microsoft.Build.Shared.FileUtilities.AttemptToShortenPath(projects[i].ItemSpec); strArray[i] = Path.GetDirectoryName(path); projectFileNames[i] = projects[i].ItemSpec; strArray3[i] = toolsVersion; if (!string.IsNullOrEmpty(projects[i].GetMetadata("Properties"))) { Hashtable hashtable; if (!PropertyParser.GetTableWithEscaping(log, Microsoft.Build.Shared.ResourceUtilities.FormatResourceString("General.OverridingProperties", new object[] { projectFileNames[i] }), "Properties", projects[i].GetMetadata("Properties").Split(new char[] { ';' }), out hashtable)) { return(false); } globalProperties[i] = hashtable; } if (undefineProperties != null) { removeGlobalProperties[i] = new List <string>(undefineProperties); } string metadata = projects[i].GetMetadata("UndefineProperties"); if (!string.IsNullOrEmpty(metadata)) { string[] strArray4 = metadata.Split(new char[] { ';' }); if (removeGlobalProperties[i] == null) { removeGlobalProperties[i] = new List <string>(strArray4.Length); } if ((log != null) && (strArray4.Length > 0)) { log.LogMessageFromResources(MessageImportance.Low, "General.ProjectUndefineProperties", new object[] { projectFileNames[i] }); foreach (string str3 in strArray4) { removeGlobalProperties[i].Add(str3); log.LogMessageFromText(string.Format(CultureInfo.InvariantCulture, " {0}", new object[] { str3 }), MessageImportance.Low); } } } if (!string.IsNullOrEmpty(projects[i].GetMetadata("AdditionalProperties"))) { Hashtable hashtable2; if (!PropertyParser.GetTableWithEscaping(log, Microsoft.Build.Shared.ResourceUtilities.FormatResourceString("General.AdditionalProperties", new object[] { projectFileNames[i] }), "AdditionalProperties", projects[i].GetMetadata("AdditionalProperties").Split(new char[] { ';' }), out hashtable2)) { return(false); } Hashtable hashtable3 = new Hashtable(StringComparer.OrdinalIgnoreCase); if (globalProperties[i] != null) { foreach (DictionaryEntry entry in globalProperties[i]) { if (!hashtable2.Contains(entry.Key)) { hashtable3.Add(entry.Key, entry.Value); } } } foreach (DictionaryEntry entry2 in hashtable2) { hashtable3.Add(entry2.Key, entry2.Value); } globalProperties[i] = hashtable3; } if (!string.IsNullOrEmpty(projects[i].GetMetadata("ToolsVersion"))) { strArray3[i] = projects[i].GetMetadata("ToolsVersion"); } } } foreach (string[] strArray5 in targetLists) { if (stopOnFirstFailure && !flag) { log.LogMessageFromResources(MessageImportance.Low, "MSBuild.SkippingRemainingTargets", new object[0]); return(flag); } bool flag2 = true; BuildEngineResult result = buildEngine.BuildProjectFilesInParallel(projectFileNames, strArray5, globalProperties, removeGlobalProperties, strArray3, true); flag2 = result.Result; targetOutputsPerProject = result.TargetOutputsPerProject; flag = flag && flag2; if (flag2) { for (int j = 0; j < projects.Length; j++) { IEnumerable enumerable = (strArray5 != null) ? ((IEnumerable)strArray5) : ((IEnumerable)targetOutputsPerProject[j].Keys); foreach (string str4 in enumerable) { if (targetOutputsPerProject[j].ContainsKey(str4)) { ITaskItem[] c = targetOutputsPerProject[j][str4]; foreach (ITaskItem item in c) { if (projects[j] != null) { if (rebaseOutputs) { try { item.ItemSpec = Path.Combine(strArray[j], item.ItemSpec); } catch (ArgumentException exception) { log.LogWarningWithCodeFromResources(null, projects[j].ItemSpec, 0, 0, 0, 0, "MSBuild.CannotRebaseOutputItemPath", new object[] { item.ItemSpec, exception.Message }); } } projects[j].CopyMetadataTo(item); if (string.IsNullOrEmpty(item.GetMetadata("MSBuildSourceProjectFile"))) { item.SetMetadata("MSBuildSourceProjectFile", projects[j].GetMetadata("FullPath")); } } if (string.IsNullOrEmpty(item.GetMetadata("MSBuildSourceTargetName"))) { item.SetMetadata("MSBuildSourceTargetName", str4); } } targetOutputs.AddRange(c); } } } } } return(flag); }
/// <summary> /// Processes the specified logging message and logs in with a <see cref="TaskLoggingHelper" />. /// </summary> /// <param name="message">The JSON message to log.</param> protected override void Process(string message) { if (string.IsNullOrWhiteSpace(message)) { // Ignore messages that are null or empty lines. Actual empty lines will still come in as JSON objects. return; } // Check if the message is JSON before attempting to deserialize it if (message.Length >= 2 && message[0] == '{' && message[message.Length - 1] == '}') { ConsoleOutLogMessage consoleOutLogMessage; try { consoleOutLogMessage = JsonConvert.DeserializeObject <ConsoleOutLogMessage>(message); } catch (Exception) { // Log the raw message if it couldn't be deserialized _log.LogMessageFromText(message, MessageImportance.Low); return; } // Convert the ConsoleOutLogMessage object to the corresponding MSBuild event object and log it switch (consoleOutLogMessage.MessageType) { case ConsoleOutLogMessageType.Error: _log.LogError( subcategory: consoleOutLogMessage.Subcategory, errorCode: consoleOutLogMessage.Code, helpKeyword: consoleOutLogMessage.HelpKeyword, file: consoleOutLogMessage.File, lineNumber: consoleOutLogMessage.LineNumber, columnNumber: consoleOutLogMessage.ColumnNumber, endLineNumber: consoleOutLogMessage.EndLineNumber, endColumnNumber: consoleOutLogMessage.EndColumnNumber, message: consoleOutLogMessage.Message); return; case ConsoleOutLogMessageType.Warning: _log.LogWarning( subcategory: consoleOutLogMessage.Subcategory, warningCode: consoleOutLogMessage.Code, helpKeyword: consoleOutLogMessage.HelpKeyword, file: consoleOutLogMessage.File, lineNumber: consoleOutLogMessage.LineNumber, columnNumber: consoleOutLogMessage.ColumnNumber, endLineNumber: consoleOutLogMessage.EndLineNumber, endColumnNumber: consoleOutLogMessage.EndColumnNumber, message: consoleOutLogMessage.Message); return; case ConsoleOutLogMessageType.Message: _log.LogMessageFromText(consoleOutLogMessage.Message, consoleOutLogMessage.Importance); return; default: throw new ArgumentOutOfRangeException( paramName: nameof(message), message: nameof(consoleOutLogMessage.MessageType)); } } }
internal static async Task <bool> ExecuteTargets( ITaskItem[] projects, Dictionary <string, string> propertiesTable, string[] undefineProperties, List <string[]> targetLists, bool stopOnFirstFailure, bool rebaseOutputs, IBuildEngine3 buildEngine, TaskLoggingHelper log, List <ITaskItem> targetOutputs, bool unloadProjectsOnCompletion, string toolsVersion, bool skipNonexistentTargets) { bool success = true; // We don't log a message about the project and targets we're going to // build, because it'll all be in the immediately subsequent ProjectStarted event. var projectDirectory = new string[projects.Length]; var projectNames = new string[projects.Length]; var toolsVersions = new string[projects.Length]; var projectProperties = new Dictionary <string, string> [projects.Length]; var undefinePropertiesPerProject = new List <string> [projects.Length]; for (int i = 0; i < projectNames.Length; i++) { projectNames[i] = null; projectProperties[i] = propertiesTable; if (projects[i] != null) { // Retrieve projectDirectory only the first time. It never changes anyway. string projectPath = FileUtilities.AttemptToShortenPath(projects[i].ItemSpec); projectDirectory[i] = Path.GetDirectoryName(projectPath); projectNames[i] = projects[i].ItemSpec; toolsVersions[i] = toolsVersion; // If the user specified a different set of global properties for this project, then // parse the string containing the properties if (!String.IsNullOrEmpty(projects[i].GetMetadata("Properties"))) { if (!PropertyParser.GetTableWithEscaping (log, ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("General.OverridingProperties", projectNames[i]), "Properties", projects[i].GetMetadata("Properties").Split(MSBuildConstants.SemicolonChar, StringSplitOptions.RemoveEmptyEntries), out Dictionary <string, string> preProjectPropertiesTable) ) { return(false); } projectProperties[i] = preProjectPropertiesTable; } if (undefineProperties != null) { undefinePropertiesPerProject[i] = new List <string>(undefineProperties); } // If the user wanted to undefine specific global properties for this project, parse // that string and remove them now. string projectUndefineProperties = projects[i].GetMetadata("UndefineProperties"); if (!String.IsNullOrEmpty(projectUndefineProperties)) { string[] propertiesToUndefine = projectUndefineProperties.Split(MSBuildConstants.SemicolonChar, StringSplitOptions.RemoveEmptyEntries); if (undefinePropertiesPerProject[i] == null) { undefinePropertiesPerProject[i] = new List <string>(propertiesToUndefine.Length); } if (log != null && propertiesToUndefine.Length > 0) { log.LogMessageFromResources(MessageImportance.Low, "General.ProjectUndefineProperties", projectNames[i]); foreach (string property in propertiesToUndefine) { undefinePropertiesPerProject[i].Add(property); log.LogMessageFromText(String.Format(CultureInfo.InvariantCulture, " {0}", property), MessageImportance.Low); } } } // If the user specified a different set of global properties for this project, then // parse the string containing the properties if (!String.IsNullOrEmpty(projects[i].GetMetadata("AdditionalProperties"))) { if (!PropertyParser.GetTableWithEscaping (log, ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("General.AdditionalProperties", projectNames[i]), "AdditionalProperties", projects[i].GetMetadata("AdditionalProperties").Split(MSBuildConstants.SemicolonChar, StringSplitOptions.RemoveEmptyEntries), out Dictionary <string, string> additionalProjectPropertiesTable) ) { return(false); } var combinedTable = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); // First copy in the properties from the global table that not in the additional properties table if (projectProperties[i] != null) { foreach (KeyValuePair <string, string> entry in projectProperties[i]) { if (!additionalProjectPropertiesTable.ContainsKey(entry.Key)) { combinedTable.Add(entry.Key, entry.Value); } } } // Add all the additional properties foreach (KeyValuePair <string, string> entry in additionalProjectPropertiesTable) { combinedTable.Add(entry.Key, entry.Value); } projectProperties[i] = combinedTable; } // If the user specified a different toolsVersion for this project - then override the setting if (!String.IsNullOrEmpty(projects[i].GetMetadata("ToolsVersion"))) { toolsVersions[i] = projects[i].GetMetadata("ToolsVersion"); } } } foreach (string[] targetList in targetLists) { if (stopOnFirstFailure && !success) { // Inform the user that we skipped the remaining targets StopOnFirstFailure=true. log.LogMessageFromResources(MessageImportance.Low, "MSBuild.SkippingRemainingTargets"); // We have encountered a failure. Caller has requested that we not // continue with remaining targets. break; } // Send the project off to the build engine. By passing in null to the // first param, we are indicating that the project to build is the same // as the *calling* project file. var taskHost = (TaskHost)buildEngine; BuildEngineResult result = await taskHost.InternalBuildProjects(projectNames, targetList, projectProperties, undefinePropertiesPerProject, toolsVersions, true /* ask that target outputs are returned in the buildengineresult */, skipNonexistentTargets); bool currentTargetResult = result.Result; IList <IDictionary <string, ITaskItem[]> > targetOutputsPerProject = result.TargetOutputsPerProject; success = success && currentTargetResult; // If the engine was able to satisfy the build request if (currentTargetResult) { for (int i = 0; i < projects.Length; i++) { IEnumerable <string> nonNullTargetList = targetList ?? targetOutputsPerProject[i].Keys; foreach (string targetName in nonNullTargetList) { if (targetOutputsPerProject[i].ContainsKey(targetName)) { ITaskItem[] outputItemsFromTarget = targetOutputsPerProject[i][targetName]; foreach (ITaskItem outputItemFromTarget in outputItemsFromTarget) { // No need to rebase if the calling project is the same as the callee project // (project == null). Also no point in trying to copy item metadata either, // because no items were passed into the Projects parameter! if (projects[i] != null) { // Rebase the output item paths if necessary. No need to rebase if the calling // project is the same as the callee project (project == null). if (rebaseOutputs) { try { outputItemFromTarget.ItemSpec = Path.Combine(projectDirectory[i], outputItemFromTarget.ItemSpec); } catch (ArgumentException e) { log.LogWarningWithCodeFromResources(null, projects[i].ItemSpec, 0, 0, 0, 0, "MSBuild.CannotRebaseOutputItemPath", outputItemFromTarget.ItemSpec, e.Message); } } // Copy the custom item metadata from the "Projects" items to these // output items. projects[i].CopyMetadataTo(outputItemFromTarget); // Set a metadata on the output items called "MSBuildProjectFile" which tells you which project file produced this item. if (String.IsNullOrEmpty(outputItemFromTarget.GetMetadata(ItemMetadataNames.msbuildSourceProjectFile))) { outputItemFromTarget.SetMetadata(ItemMetadataNames.msbuildSourceProjectFile, projects[i].GetMetadata(FileUtilities.ItemSpecModifiers.FullPath)); } } // Set a metadata on the output items called "MSBuildTargetName" which tells you which target produced this item. if (String.IsNullOrEmpty(outputItemFromTarget.GetMetadata(ItemMetadataNames.msbuildSourceTargetName))) { outputItemFromTarget.SetMetadata(ItemMetadataNames.msbuildSourceTargetName, targetName); } } targetOutputs.AddRange(outputItemsFromTarget); } } } } } return(success); }
internal static bool GetTableWithEscaping(TaskLoggingHelper log, string parameterName, string syntaxName, string[] propertyNameValueStrings, out Dictionary <string, string> finalPropertiesTable) { finalPropertiesTable = null; if (propertyNameValueStrings != null) { finalPropertiesTable = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); var finalPropertiesList = new List <PropertyNameValuePair>(); // Loop through the array. Each string in the array should be of the form: // MyPropName=MyPropValue foreach (string propertyNameValueString in propertyNameValueStrings) { // Find the first '=' sign in the string. int indexOfEqualsSign = propertyNameValueString.IndexOf('='); if (indexOfEqualsSign != -1) { // If we found one, then grab the stuff before it and put it into "propertyName", // and grab the stuff after it and put it into "propertyValue". But trim the // whitespace from beginning and end of both name and value. (When authoring a // project/targets file, people like to use whitespace and newlines to pretty up // the file format.) string propertyName = propertyNameValueString.Substring(0, indexOfEqualsSign).Trim(); string propertyValue = EscapingUtilities.Escape(propertyNameValueString.Substring(indexOfEqualsSign + 1).Trim()); // Make sure we have a property name and property value (though the value is allowed to be blank). if (propertyName.Length == 0) { // No property name? That's no good to us. log?.LogErrorWithCodeFromResources("General.InvalidPropertyError", syntaxName, propertyNameValueString); return(false); } // Store the property in our list. finalPropertiesList.Add(new PropertyNameValuePair(propertyName, propertyValue)); } else { // There's no '=' sign in the string. When this happens, we treat this string as basically // an appendage on the value of the previous property. For example, if the project file contains // // <PropertyGroup> // <WarningsAsErrors>1234;5678;9999</WarningsAsErrors> // </PropertyGroup> // <Target Name="Build"> // <MSBuild Projects="ConsoleApplication1.csproj" // Properties="WarningsAsErrors=$(WarningsAsErrors)"/> // </Target> // // , then this method (GetTableWithEscaping) will see this: // // propertyNameValueStrings[0] = "WarningsAsErrors=1234" // propertyNameValueStrings[1] = "5678" // propertyNameValueStrings[2] = "9999" // // And what we actually want to end up with in our final hashtable is this: // // NAME VALUE // =================== ================================ // WarningsAsErrors 1234;5678;9999 // if (finalPropertiesList.Count > 0) { // There was a property definition previous to this one. Append the current string // to that previous value, using semicolon as a separator. string propertyValue = EscapingUtilities.Escape(propertyNameValueString.Trim()); finalPropertiesList[finalPropertiesList.Count - 1].Value.Add(propertyValue); } else { // No equals sign in the very first property? That's a problem. log?.LogErrorWithCodeFromResources("General.InvalidPropertyError", syntaxName, propertyNameValueString); return(false); } } } // Convert the data in the List to a Hashtable, because that's what the MSBuild task eventually // needs to pass onto the engine. log?.LogMessageFromText(parameterName, MessageImportance.Low); using SpanBasedStringBuilder stringBuilder = Strings.GetSpanBasedStringBuilder(); foreach (PropertyNameValuePair propertyNameValuePair in finalPropertiesList) { stringBuilder.Clear(); bool needsSemicolon = false; foreach (string valueFragment in propertyNameValuePair.Value) { if (needsSemicolon) { stringBuilder.Append(";"); } needsSemicolon = true; stringBuilder.Append(valueFragment); } string propertyValue = stringBuilder.ToString(); finalPropertiesTable[propertyNameValuePair.Name] = propertyValue; log?.LogMessageFromText( $" {propertyNameValuePair.Name}={propertyValue}", MessageImportance.Low); } } return(true); }