예제 #1
0
        /// <summary>
        /// Builds multiple project files in parallel.  This is the method the old MSBuild task invokes.
        /// Thread safe.
        /// </summary>
        /// <param name="projectFileNames">The list of projects to build</param>
        /// <param name="targetNames">The set of targets to build</param>
        /// <param name="globalProperties">The global properties to use for each project</param>
        /// <param name="targetOutputsPerProject">The outputs for each target on each project</param>
        /// <param name="toolsVersion">The tools versions to use</param>
        /// <param name="useResultsCache">Whether to use the results cache</param>
        /// <param name="unloadProjectsOnCompletion">Whether to unload projects when we are done.</param>
        /// <returns>True on success, false otherwise.</returns>
        public bool BuildProjectFilesInParallel(string[] projectFileNames, string[] targetNames, System.Collections.IDictionary[] globalProperties, System.Collections.IDictionary[] targetOutputsPerProject, string[] toolsVersion, bool useResultsCache, bool unloadProjectsOnCompletion)
        {
            bool includeTargetOutputs = (targetOutputsPerProject != null);

            // If the caller supplies an array to put the target outputs in, it must have the same length as the array of project file names they provided, too.
            // "MSB3094: "{2}" refers to {0} item(s), and "{3}" refers to {1} item(s). They must have the same number of items."
            ErrorUtilities.VerifyThrowArgument((targetOutputsPerProject == null) || (projectFileNames.Length == targetOutputsPerProject.Length), "General.TwoVectorsMustHaveSameLength", projectFileNames.Length, targetOutputsPerProject?.Length ?? 0, "projectFileNames", "targetOutputsPerProject");

            BuildEngineResult result = BuildProjectFilesInParallel(projectFileNames, targetNames, globalProperties, new List <String> [projectFileNames.Length], toolsVersion, includeTargetOutputs);

            if (includeTargetOutputs)
            {
                // Copy results from result.TargetOutputsPerProject to targetOutputsPerProject
                // We should always have the same number of entries - although an entry might be empty if a project failed.
                ErrorUtilities.VerifyThrow(targetOutputsPerProject.Length == result.TargetOutputsPerProject.Count, "{0} != {1}", targetOutputsPerProject.Length, result.TargetOutputsPerProject.Count);

                for (int i = 0; i < targetOutputsPerProject.Length; i++)
                {
                    if (targetOutputsPerProject[i] != null)
                    {
                        foreach (KeyValuePair <string, ITaskItem[]> output in result.TargetOutputsPerProject[i])
                        {
                            targetOutputsPerProject[i].Add(output.Key, output.Value);
                        }
                    }
                }
            }

            BuildRequestsSucceeded = result.Result;

            return(result.Result);
        }
예제 #2
0
        public bool BuildProjectFilesInParallel
        (
            string[] projectFileNames,
            string[] targetNames,
            IDictionary[] globalProperties,
            IDictionary[] targetOutputsPerProject,
            string[] toolsVersion,
            bool useResultsCache,
            bool unloadProjectsOnCompletion
        )
        {
            bool includeTargetOutputs = targetOutputsPerProject != null;

            BuildEngineResult result = BuildProjectFilesInParallel(projectFileNames, targetNames, globalProperties, new List <String> [projectFileNames.Length], toolsVersion, includeTargetOutputs);

            if (includeTargetOutputs)
            {
                for (int i = 0; i < targetOutputsPerProject.Length; i++)
                {
                    if (targetOutputsPerProject[i] != null)
                    {
                        foreach (KeyValuePair <string, ITaskItem[]> output in result.TargetOutputsPerProject[i])
                        {
                            targetOutputsPerProject[i].Add(output.Key, output.Value);
                        }
                    }
                }
            }

            return(result.Result);
        }
 private bool ExecuteCore()
 {
     var assemblyNameToProjectFile =
         JsonConvert.DeserializeObject<Dictionary<string, LiveReferenceData>>(File.ReadAllText(LiveReferenceCacheFile));
     var referencePaths = new List<ITaskItem>();
     var referencedProjects = new List<LiveReferenceData>();
     foreach (var reference in References)
     {
         var assemblyName = reference.GetMetadata("FileName");
         LiveReferenceData referenceData;
         if (assemblyNameToProjectFile.TryGetValue(assemblyName, out referenceData))
         {
             referencedProjects.Add(referenceData);
         }
         else
         {
             referencePaths.Add(reference);
         }
     }
     var additionalAssemblyReferences =
         AdditionalAssemblyReferences.Split(';').Where(s => !string.IsNullOrEmpty(s)).ToList();
     foreach (var assemblyName in additionalAssemblyReferences)
     {
         referencedProjects.Add(assemblyNameToProjectFile[assemblyName]);
     }
     var projectsToBuild = new List<string>();
     foreach (var liveReference in referencedProjects)
     {
         if (!File.Exists(liveReference.TargetPath))
         {
             Log.LogMessage(MessageImportance.Normal, "Reference '{0}' doesn't exist. It will be built.", liveReference.TargetPath);
             projectsToBuild.Add(liveReference.Project);
         }
         else
         {
             Log.LogMessage(MessageImportance.Normal, "Reference '{0}' exists", liveReference.TargetPath);
         }
     }
     BuildEngineResult result = BuildEngine3.BuildProjectFilesInParallel(
         projectsToBuild.ToArray(),
         "Build",
         new Dictionary<string, string>(),
         new[] {"CustomAfterBuildCommonTargets"},
         null,
         false
     );
     if (!result.Result)
     {
         Log.LogError("Failed to resolve references.");
         return false;
     }
     referencePaths.AddRange(referencedProjects.Select(p => new TaskItem(p.TargetPath)));
     ReferencePaths = referencePaths.ToArray();
     return true;
 }
예제 #4
0
        private bool ExecuteCore()
        {
            var properties = new Dictionary <string, string>();

            foreach (var prop in SetProperties.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
            {
                var key   = prop.Substring(0, prop.IndexOf('=')).Trim();
                var value = prop.Substring(prop.IndexOf('=') + 1).Trim();
                if (!string.IsNullOrEmpty(key))
                {
                    properties[key] = value;
                }
            }
            var projectFiles = CandidateReferenceProjects
                               .Select(p => p.GetMetadata("FullPath"))
                               .ToArray();
            var propertyArray = new IDictionary[projectFiles.Length];

            for (int i = 0; i < projectFiles.Length; i++)
            {
                propertyArray[i] = properties;
            }
            var removePropertiesArray = Enumerable.Repeat((IList <string>)UndefineProperties.Split(new[] { ';' }).Select(p => p.Trim()).Where(s => !string.IsNullOrEmpty(s)).ToArray(), propertyArray.Length).ToArray();
            BuildEngineResult result  = BuildEngine3.BuildProjectFilesInParallel(
                projectFiles,
                Enumerable.Repeat("GetTargetPath", projectFiles.Length).ToArray(),
                propertyArray,
                removePropertiesArray,
                new string[projectFiles.Length],
                true
                );

            if (!result.Result)
            {
                Log.LogError("Building 'GetTargetPath' Failed.");
                return(false);
            }
            var assemblyNameToProject = new Dictionary <string, LiveReferenceData>();

            for (int i = 0; i < projectFiles.Length; i++)
            {
                string projectFile = projectFiles[i];
                IDictionary <string, ITaskItem[]> targetOutputs = result.TargetOutputsPerProject[i];
                ITaskItem targetPath   = targetOutputs["GetTargetPath"].First();
                string    assemblyName = targetPath.GetMetadata("FileName");
                assemblyNameToProject[assemblyName] = new LiveReferenceData
                {
                    Project    = projectFile,
                    TargetPath = targetPath.GetMetadata("FullPath")
                };
            }
            File.WriteAllText(LiveReferenceCacheFile, JsonConvert.SerializeObject(assemblyNameToProject, Formatting.Indented));
            return(true);
        }
예제 #5
0
        /// <summary>
        /// Called by the internal MSBuild task.
        /// Does not take the lock because it is called by another request builder thread.
        /// </summary>
        public async Task <BuildEngineResult> InternalBuildProjects(string[] projectFileNames, string[] targetNames, IDictionary[] globalProperties, IList <String>[] undefineProperties, string[] toolsVersion, bool returnTargetOutputs, bool skipNonexistentTargets = false)
        {
            ErrorUtilities.VerifyThrowArgumentNull(projectFileNames, "projectFileNames");
            ErrorUtilities.VerifyThrowArgumentNull(globalProperties, "globalProperties");
            VerifyActiveProxy();

            BuildEngineResult result;

            if (projectFileNames.Length == 1 && projectFileNames[0] == null && globalProperties[0] == null && (undefineProperties == null || undefineProperties[0] == null) && toolsVersion[0] == null)
            {
                bool overallSuccess = true;
                List <IDictionary <string, ITaskItem[]> > targetOutputsPerProject = null;

                // This is really a legacy CallTarget invocation
                ITargetResult[] results = await _targetBuilderCallback.LegacyCallTarget(targetNames, ContinueOnError, _taskLocation);

                if (returnTargetOutputs)
                {
                    targetOutputsPerProject = new List <IDictionary <string, ITaskItem[]> >(1);
                    targetOutputsPerProject.Add(new Dictionary <string, ITaskItem[]>(StringComparer.OrdinalIgnoreCase));
                }

                for (int i = 0; i < targetNames.Length; i++)
                {
                    targetOutputsPerProject[0][targetNames[i]] = results[i].Items;
                    if (results[i].ResultCode == TargetResultCode.Failure)
                    {
                        overallSuccess = false;
                    }
                }

                result = new BuildEngineResult(overallSuccess, targetOutputsPerProject);
                BuildRequestsSucceeded = overallSuccess;
            }
            else
            {
                // Post the request, then yield up the thread.
                result = await BuildProjectFilesInParallelAsync(projectFileNames, targetNames, globalProperties, undefineProperties, toolsVersion, true /* ask that target outputs are returned in the buildengineresult */, skipNonexistentTargets);
            }

            return(result);
        }
예제 #6
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);
        }
예제 #7
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))
예제 #8
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);
        }