Exemplo n.º 1
0
        /// <summary>
        /// Loads projects.
        /// </summary>
        /// <param name="msbuildExeFileInfo">The <see cref="FileInfo" /> of MSBuild.exe.</param>
        /// <param name="projectCollection">The <see cref="ProjectCollection" /> to use when loading projects.</param>
        /// <param name="entryProjects">The <see cref="IEnumerable{String}" /> of entry projects.</param>
        /// <param name="globalProperties">The <see cref="IDictionary{String,String}" /> of global properties to use.</param>
        /// <param name="logger">A <see cref="ISlnGenLogger" /> to use as a logger.</param>
        /// <returns>A <see cref="Tuple{TimeSpan, Int32}" /> with the amount of time it took to load projects and the total number of projects that were loaded.</returns>
        public static (TimeSpan projectEvaluation, int projectCount) LoadProjects(FileInfo msbuildExeFileInfo, ProjectCollection projectCollection, IEnumerable <string> entryProjects, IDictionary <string, string> globalProperties, ISlnGenLogger logger)
        {
            if (logger.HasLoggedErrors)
            {
                return(TimeSpan.Zero, 0);
            }

            logger.LogMessageHigh("Loading project references...");

            Stopwatch sw = Stopwatch.StartNew();

            IProjectLoader projectLoader = Create(msbuildExeFileInfo, logger);

            try
            {
                projectLoader.LoadProjects(entryProjects, projectCollection, globalProperties);
            }
            catch (InvalidProjectFileException)
            {
                return(TimeSpan.Zero, 0);
            }
            catch (Exception e)
            {
                logger.LogError(e.ToString());
                return(TimeSpan.Zero, 0);
            }

            sw.Stop();

            logger.LogMessageNormal($"Loaded {projectCollection.LoadedProjects.Count:N0} project(s) in {sw.ElapsedMilliseconds:N0}ms");

            return(sw.Elapsed, projectCollection.LoadedProjects.Count);
        }
Exemplo n.º 2
0
        public static ProjectCollection LoadProjectsAndReferences(
            IDictionary <string, string> globalProperties,
            string toolsVersion,
            IBuildEngine buildEngine,
            bool collectStats,
            string projectFullPath,
            IEnumerable <ITaskItem> projectReferences,
            ISlnGenLogger logger)
        {
            // Create an MSBuildProject loader with the same global properties of the project that requested a solution file
            MSBuildProjectLoader projectLoader = new MSBuildProjectLoader(globalProperties, toolsVersion, buildEngine, ProjectLoadSettings.IgnoreMissingImports)
            {
                CollectStats = collectStats,
            };

            logger.LogMessageHigh("Loading project references...");

            ProjectCollection projectCollection = projectLoader.LoadProjectsAndReferences(projectReferences.Select(i => i.GetMetadata("FullPath")).Concat(new[] { projectFullPath }));

            logger.LogMessageNormal($"Loaded {projectCollection.LoadedProjects.Count} project(s)");

            if (collectStats)
            {
                LogStatistics(projectLoader, logger);
            }

            return(projectCollection);
        }
Exemplo n.º 3
0
        private (string solutionFileFullPath, int customProjectTypeGuidCount, int solutionItemCount) GenerateSolutionFile(IEnumerable <Project> projects, ISlnGenLogger logger)
        {
            Project project = projects.First();

            IReadOnlyDictionary <string, Guid> customProjectTypeGuids = SlnProject.GetCustomProjectTypeGuids(project);

            IReadOnlyCollection <string> solutionItems = SlnProject.GetSolutionItems(project, logger).ToList();

            string solutionFileFullPath = _arguments.SolutionFileFullPath?.LastOrDefault();

            if (solutionFileFullPath.IsNullOrWhiteSpace())
            {
                string solutionDirectoryFullPath = _arguments.SolutionDirectoryFullPath?.LastOrDefault();

                if (solutionDirectoryFullPath.IsNullOrWhiteSpace())
                {
                    solutionDirectoryFullPath = project.DirectoryPath;
                }

                string solutionFileName = Path.ChangeExtension(Path.GetFileName(project.FullPath), "sln");

                solutionFileFullPath = Path.Combine(solutionDirectoryFullPath, solutionFileName);
            }

            logger.LogMessageHigh($"Generating Visual Studio solution \"{solutionFileFullPath}\" ...");

            if (customProjectTypeGuids.Count > 0)
            {
                logger.LogMessageLow("Custom Project Type GUIDs:");
                foreach (KeyValuePair <string, Guid> item in customProjectTypeGuids)
                {
                    logger.LogMessageLow("  {0} = {1}", item.Key, item.Value);
                }
            }

            SlnFile solution = new SlnFile
            {
                Platforms      = _arguments.GetPlatforms(),
                Configurations = _arguments.GetConfigurations(),
            };

            if (SlnFile.TryParseExistingSolution(solutionFileFullPath, out Guid solutionGuid, out IReadOnlyDictionary <string, Guid> projectGuidsByPath))
            {
                logger.LogMessageNormal("Updating existing solution file and reusing Visual Studio cache");

                solution.SolutionGuid         = solutionGuid;
                solution.ExistingProjectGuids = projectGuidsByPath;

                _arguments.LoadProjectsInVisualStudio = new[] { bool.TrueString };
            }

            solution.AddProjects(projects, customProjectTypeGuids, project.FullPath);

            solution.AddSolutionItems(solutionItems);

            solution.Save(solutionFileFullPath, _arguments.EnableFolders(), _arguments.EnableCollapseFolders());

            return(solutionFileFullPath, customProjectTypeGuids.Count, solutionItems.Count);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Gets specified projects or all projects in the current working directory.
        /// </summary>
        /// <returns>An <see cref="IEnumerable{String}" /> containing the full paths to projects to generate a solution for.</returns>
        private IEnumerable <string> GetEntryProjectPaths(ISlnGenLogger logger)
        {
            if (_arguments.Projects == null || !_arguments.Projects.Any())
            {
                logger.LogMessageNormal("Searching \"{0}\" for projects", Environment.CurrentDirectory);
                bool projectFound = false;

                foreach (string projectPath in Directory.EnumerateFiles(Environment.CurrentDirectory, "*.*proj"))
                {
                    projectFound = true;

                    logger.LogMessageNormal("Generating solution for project \"{0}\"", projectPath);

                    yield return(projectPath);
                }

                if (!projectFound)
                {
                    logger.LogError("No projects found in the current directory. Please specify the path to the project you want to generate a solution for.");
                }

                yield break;
            }

            foreach (string projectPath in _arguments.Projects.Select(Path.GetFullPath))
            {
                if (!File.Exists(projectPath))
                {
                    logger.LogError(string.Format("Project file \"{0}\" does not exist", projectPath));
                    continue;
                }

                logger.LogMessageNormal("Generating solution for project \"{0}\"", projectPath);

                yield return(projectPath);
            }
        }
Exemplo n.º 5
0
        private (TimeSpan projectEvaluation, int projectCount) LoadProjects(ProjectCollection projectCollection, ISlnGenLogger logger)
        {
            List <string> entryProjects = GetEntryProjectPaths(logger).ToList();

            if (logger.HasLoggedErrors)
            {
                return(TimeSpan.Zero, 0);
            }

            logger.LogMessageHigh("Loading project references...");

            Stopwatch sw = Stopwatch.StartNew();

            IProjectLoader projectLoader = ProjectLoaderFactory.Create(_msbuildExePath, logger);

            IDictionary <string, string> globalProperties = GetGlobalProperties();

            using (new MSBuildFeatureFlags
            {
                CacheFileEnumerations = true,
                LoadAllFilesAsReadOnly = true,
                MSBuildSkipEagerWildCardEvaluationRegexes = true,
                UseSimpleProjectRootElementCacheConcurrency = true,
                MSBuildExePath = _msbuildExePath.FullName,
            })
            {
                try
                {
                    projectLoader.LoadProjects(entryProjects, projectCollection, globalProperties);
                }
                catch (InvalidProjectFileException)
                {
                    return(TimeSpan.Zero, 0);
                }
                catch (Exception e)
                {
                    logger.LogError(e.ToString());
                    return(TimeSpan.Zero, 0);
                }
            }

            sw.Stop();

            logger.LogMessageNormal($"Loaded {projectCollection.LoadedProjects.Count:N0} project(s) in {sw.ElapsedMilliseconds:N0}ms");

            return(sw.Elapsed, projectCollection.LoadedProjects.Count);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Generates a solution file.
        /// </summary>
        /// <param name="arguments">The current <see cref="ProgramArguments" />.</param>
        /// <param name="projects">A <see cref="IEnumerable{String}" /> containing the entry projects.</param>
        /// <param name="logger">A <see cref="ISlnGenLogger" /> to use for logging.</param>
        /// <returns>A <see cref="Tuple{String, Int32, Int32, Guid}" /> with the full path to the solution file, the count of custom project type GUIDs used, the count of solution items, and the solution GUID.</returns>
        public static (string solutionFileFullPath, int customProjectTypeGuidCount, int solutionItemCount, Guid solutionGuid) GenerateSolutionFile(ProgramArguments arguments, IEnumerable <Project> projects, ISlnGenLogger logger)
        {
            List <Project> projectList = projects.ToList();

            Project firstProject = projectList.First();

            IReadOnlyDictionary <string, Guid> customProjectTypeGuids = SlnProject.GetCustomProjectTypeGuids(firstProject);

            IReadOnlyCollection <string> solutionItems = SlnProject.GetSolutionItems(firstProject, logger).ToList();

            string solutionFileFullPath = arguments.SolutionFileFullPath?.LastOrDefault();

            if (solutionFileFullPath.IsNullOrWhiteSpace())
            {
                string solutionDirectoryFullPath = arguments.SolutionDirectoryFullPath?.LastOrDefault();

                if (solutionDirectoryFullPath.IsNullOrWhiteSpace())
                {
                    solutionDirectoryFullPath = firstProject.DirectoryPath;
                }

                string solutionFileName = Path.ChangeExtension(Path.GetFileName(firstProject.FullPath), "sln");

                solutionFileFullPath = Path.Combine(solutionDirectoryFullPath !, solutionFileName);
            }

            logger.LogMessageHigh($"Generating Visual Studio solution \"{solutionFileFullPath}\" ...");

            if (customProjectTypeGuids.Count > 0)
            {
                logger.LogMessageLow("Custom Project Type GUIDs:");
                foreach (KeyValuePair <string, Guid> item in customProjectTypeGuids)
                {
                    logger.LogMessageLow("  {0} = {1}", item.Key, item.Value);
                }
            }

            SlnFile solution = new SlnFile
            {
                Platforms      = arguments.GetPlatforms(),
                Configurations = arguments.GetConfigurations(),
            };

            if (SlnFile.TryParseExistingSolution(solutionFileFullPath, out Guid solutionGuid, out IReadOnlyDictionary <string, Guid> projectGuidsByPath))
            {
                logger.LogMessageNormal("Updating existing solution file and reusing Visual Studio cache");

                solution.SolutionGuid         = solutionGuid;
                solution.ExistingProjectGuids = projectGuidsByPath;

                arguments.LoadProjectsInVisualStudio = new[] { bool.TrueString };
            }

            solution.AddProjects(projectList, customProjectTypeGuids, arguments.IgnoreMainProject ? null : firstProject.FullPath);

            solution.AddSolutionItems(solutionItems);

            if (!arguments.EnableFolders())
            {
                foreach (SlnProject project in solution._projects.Distinct(new EqualityComparer <SlnProject>((x, y) => string.Equals(x.SolutionFolder, y.SolutionFolder)))
                         .Where(i => !string.IsNullOrWhiteSpace(i.SolutionFolder) && i.SolutionFolder.Contains(Path.DirectorySeparatorChar)))
                {
                    logger.LogError($"The value of SlnGenSolutionFolder \"{project.SolutionFolder}\" cannot contain directory separators.");
                }
            }

            if (!logger.HasLoggedErrors)
            {
                solution.Save(solutionFileFullPath, arguments.EnableFolders(), arguments.EnableCollapseFolders());
            }

            return(solutionFileFullPath, customProjectTypeGuids.Count, solutionItems.Count, solution.SolutionGuid);
        }
Exemplo n.º 7
0
        private int Generate()
        {
            using (SlnGenTelemetryData telemetryData = new SlnGenTelemetryData
            {
                DevEnvFullPathSpecified = !_programArguments.DevEnvFullPath.IsNullOrWhitespace(),
                EntryProjectCount = _programArguments.Projects.Length,
                Folders = _programArguments.Folders,
                LaunchVisualStudio = _programArguments.LaunchVisualStudio,
                SolutionFileFullPathSpecified = !_programArguments.SolutionFileFullPath.IsNullOrWhitespace(),
                UseBinaryLogger = _programArguments.BinaryLogger.HasValue,
                UseFileLogger = _programArguments.FileLoggerParameters.HasValue,
                UseShellExecute = _programArguments.UseShellExecute,
            })
            {
                _logger.LogMessageHigh("Loading project references...");

                Stopwatch sw = Stopwatch.StartNew();

                IDictionary <string, string> globalProperties = new Dictionary <string, string>
                {
                    ["BuildingProject"] = "false",
                    ["DesignTimeBuild"] = "true",
                    ["ExcludeRestorePackageImports"] = "true",
                };

                ICollection <ProjectGraphEntryPoint> entryProjects = _programArguments.GetProjects(_logger).Select(i => new ProjectGraphEntryPoint(i, globalProperties)).ToList();

                _ = new ProjectGraph(entryProjects, _projectCollection, CreateProjectInstance);

                sw.Stop();

                _logger.LogMessageNormal($"Loaded {_projectCollection.LoadedProjects.Count} project(s) in {sw.ElapsedMilliseconds:N2}ms");

                telemetryData.ProjectEvaluationMilliseconds = sw.ElapsedMilliseconds;
                telemetryData.ProjectEvaluationCount        = _projectCollection.LoadedProjects.Count;

                Project project = _projectCollection.LoadedProjects.First();

                Dictionary <string, Guid> customProjectTypeGuids = SlnProject.GetCustomProjectTypeGuids(project.GetItems("SlnGenCustomProjectTypeGuid").Select(i => new MSBuildProjectItem(i)));

                IReadOnlyCollection <string> solutionItems = SlnFile.GetSolutionItems(project.GetItems("SlnGenSolutionItem").Select(i => new MSBuildProjectItem(i)), _logger).ToList();

                telemetryData.CustomProjectTypeGuidCount = customProjectTypeGuids.Count;

                telemetryData.SolutionItemCount = solutionItems.Count;

                string solutionFileFullPath = SlnGenUtility.GenerateSolutionFile(
                    _projectCollection,
                    solutionFileFullPath: null,
                    projectFileFullPath: entryProjects.First().ProjectFile,
                    customProjectTypeGuids: customProjectTypeGuids,
                    folders: _programArguments.Folders,
                    solutionItems: solutionItems,
                    logger: _logger);

                if (_programArguments.LaunchVisualStudio)
                {
                    SlnGenUtility.LaunchVisualStudio(_programArguments.DevEnvFullPath, _programArguments.UseShellExecute, solutionFileFullPath, _logger);
                }

                return(_logger.HasLoggedErrors ? 1 : 0);
            }
        }