Esempio n. 1
0
 void StdOutCallback(object sender, DataReceivedEventArgs e)
 {
     if (e.Data != null)
     {
         log.LogMessageFromText(e.Data, MessageImportance.High);
     }
 }
Esempio n. 2
0
        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);
    }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        public bool Execute()
        {
            //set up support for logging
            TaskLoggingHelper loggingHelper = new TaskLoggingHelper(this);

            loggingHelper.LogMessageFromText(
                "Hello MSBuild", MessageImportance.High);

            return(true);
        }
Esempio n. 8
0
 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);
         }
     }
 }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
        /// <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))
Esempio n. 11
0
 void _logLine(string line)
 {
     _log.LogMessageFromText(line, MessageImportance.High);
 }
Esempio n. 12
0
        /// <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;
        }
Esempio n. 13
0
        /// <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;
        }
Esempio n. 14
0
        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);
        }
Esempio n. 15
0
        /// <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));
                }
            }
        }
Esempio n. 16
0
        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);
        }
Esempio n. 17
0
        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);
        }