/// <summary> /// Generates a Visual Studio (c) Solution file. /// </summary> /// <param name="programArguments">The <see cref="ProgramArguments" /> to use when generating the solution.</param> /// <param name="logger">An optional <see cref="ISlnGenLogger" /> to use for logging.</param> /// <returns>zero if it the solution was generated, otherwise non-zero.</returns> public static int Generate(ProgramArguments programArguments, ISlnGenLogger logger = null) { using (SolutionFileGenerator solutionFileGenerator = new SolutionFileGenerator(programArguments, logger)) { return(solutionFileGenerator.Generate()); } }
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); }
/// <summary> /// Gets the solution items' full paths. /// </summary> /// <param name="project">The <see cref="Project" /> containing the solution items.</param> /// <param name="logger">A <see cref="ISlnGenLogger" /> to use for logging.</param> /// <param name="fileExists">A <see cref="Func{String, Boolean}"/> to use when determining if a file exists.</param> /// <exception cref="ArgumentNullException"><paramref name="project" /> is null /// -or- /// <paramref name="logger" /> is null /// -or- /// <paramref name="fileExists" /> is null.</exception> /// <returns>An <see cref="IEnumerable{String}"/> of full paths to include as solution items.</returns> internal static IEnumerable <string> GetSolutionItems(Project project, ISlnGenLogger logger, Func <string, bool> fileExists = null) { if (project == null) { throw new ArgumentNullException(nameof(project)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } fileExists ??= File.Exists; foreach (string solutionItem in project.GetItems(MSBuildItemNames.SlnGenSolutionItem).Select(i => i.GetMetadataValue("FullPath")).Where(i => !i.IsNullOrWhiteSpace())) { if (!fileExists(solutionItem)) { logger.LogMessageLow($"The solution item \"{solutionItem}\" does not exist and will not be added to the solution.", MessageImportance.Low); } else { yield return(solutionItem); } } }
public static void GenerateSolutionFile( ProjectCollection projectCollection, string solutionFileFullPath, string projectFileFullPath, IReadOnlyDictionary <string, Guid> customProjectTypeGuids, bool folders, IEnumerable <string> solutionItems, ISlnGenLogger logger) { if (string.IsNullOrWhiteSpace(solutionFileFullPath)) { solutionFileFullPath = Path.ChangeExtension(projectFileFullPath, ".sln"); } 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(); solution.AddProjects(projectCollection, customProjectTypeGuids, projectFileFullPath); solution.AddSolutionItems(solutionItems); solution.Save(solutionFileFullPath, folders); }
public static void LogStatistics(MSBuildProjectLoader projectLoader, ISlnGenLogger logger) { logger.LogMessageLow("SlnGen Project Evaluation Performance Summary:"); foreach (KeyValuePair <string, TimeSpan> item in projectLoader.Statistics.ProjectLoadTimes.OrderByDescending(i => i.Value)) { logger.LogMessageLow($" {Math.Round(item.Value.TotalMilliseconds, 0)} ms {item.Key}", MessageImportance.Low); } }
/// <summary> /// Creates an appropriate instance of a class that implements <see cref="IProjectLoader" />. /// </summary> /// <param name="msbuildExePath">The full path to MSBuild.exe.</param> /// <param name="logger">An <see cref="ISlnGenLogger" /> object to use for logging.</param> /// <returns>An <see cref="IProjectLoader" /> object that can be used to load MSBuild projects.</returns> public static IProjectLoader Create(FileInfo msbuildExePath, ISlnGenLogger logger) { #if !NET46 FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(msbuildExePath.FullName); // MSBuild 16.4 and above use the Static Graph API if (fileVersionInfo.FileMajorPart >= 16 && fileVersionInfo.FileMinorPart >= 4) { return(new ProjectGraphProjectLoader(logger)); } #endif return(new LegacyProjectLoader(logger)); }
/// <summary> /// Creates an appropriate instance of a class that implements <see cref="IProjectLoader" />. /// </summary> /// <param name="msbuildExePath">The full path to MSBuild.exe.</param> /// <param name="logger">An <see cref="ISlnGenLogger" /> object to use for logging.</param> /// <returns>An <see cref="IProjectLoader" /> object that can be used to load MSBuild projects.</returns> private static IProjectLoader Create(FileInfo msbuildExePath, ISlnGenLogger logger) { #if !NETFRAMEWORK return(new ProjectGraphProjectLoader(logger)); #elif NET461 return(new LegacyProjectLoader(logger)); #else FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(msbuildExePath.FullName); // MSBuild 16.4 and above use the Static Graph API if (fileVersionInfo.FileMajorPart > 16 || (fileVersionInfo.FileMajorPart == 16 && fileVersionInfo.FileMinorPart >= 4)) { return(new ProjectGraphProjectLoader(logger)); } return(new LegacyProjectLoader(logger)); #endif }
private SolutionFileGenerator(ProgramArguments programArguments, ISlnGenLogger logger) { _programArguments = programArguments ?? throw new ArgumentNullException(nameof(programArguments)); _logger = logger ?? new ForwardingLogger(GetLoggers().ToArray()); _projectCollection = new ProjectCollection( globalProperties: null, loggers: new List <ILogger> { _logger as ILogger, }, remoteLoggers: null, toolsetDefinitionLocations: ToolsetDefinitionLocations.Default, maxNodeCount: 1, onlyLogCriticalEvents: false, loadProjectsReadOnly: true); }
/// <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); } }
/// <summary> /// Logs a <see cref="ProjectStartedEventArgs" /> object for the specified project. /// </summary> /// <param name="logger">An <see cref="ISlnGenLogger" /> to use.</param> /// <param name="projectInstance">The <see cref="ProjectInstance" /> of the project.</param> internal static void LogProjectStartedEvent(ISlnGenLogger logger, ProjectInstance projectInstance) { if (!logger.IsDiagnostic) { return; } int projectId = logger.NextProjectId; logger.LogEvent(new ProjectStartedEventArgs( projectId: projectId, message: $"Project \"{projectInstance.FullPath}\"", helpKeyword: null, projectFile: projectInstance.FullPath, targetNames: null, properties: projectInstance.Properties.Select(i => new DictionaryEntry(i.Name, i.EvaluatedValue)), items: projectInstance.Items.Select(i => new DictionaryEntry(i.ItemType, new ProjectItemWrapper(i))), parentBuildEventContext: BuildEventContext.Invalid, globalProperties: projectInstance.GlobalProperties, toolsVersion: null) { BuildEventContext = new BuildEventContext(BuildEventContext.InvalidSubmissionId, BuildEventContext.InvalidNodeId, projectInstance.EvaluationId, projectId, projectId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId), }); }
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); }
/// <summary> /// Initializes a new instance of the <see cref="LegacyProjectLoader"/> class. /// </summary> /// <param name="logger">An <see cref="ISlnGenLogger" /> to use for logging.</param> public LegacyProjectLoader(ISlnGenLogger logger) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); }
/// <summary> /// Creates an appropriate instance of a class that implements <see cref="IProjectLoader" />. /// </summary> /// <param name="logger">An <see cref="ISlnGenLogger" /> object to use for logging.</param> /// <returns>An <see cref="IProjectLoader" /> object that can be used to load MSBuild projects.</returns> private static IProjectLoader Create(ISlnGenLogger logger)
/// <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(); #if NET472 IProjectLoader projectLoader = Create(msbuildExeFileInfo, logger); #else IProjectLoader projectLoader = Create(logger); #endif 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); }
/// <summary> /// Gets the solution items' full paths. /// </summary> /// <param name="items">The <see cref="IEnumerable{IMSBuildItem}" /> containing the solution items.</param> /// <param name="logger">A <see cref="ISlnGenLogger" /> to use for logging.</param> /// <param name="fileExists">A <see cref="Func{String, Boolean}"/> to use when determining if a file exists.</param> /// <exception cref="ArgumentNullException"><paramref name="items" /> is <code>null</code> /// -or- /// <paramref name="logger" /> is <code>null</code> /// -or- /// <paramref name="fileExists" /> is <code>null</code>.</exception> /// <returns>An <see cref="IEnumerable{String}"/> of full paths to include as solution items.</returns> internal static IEnumerable <string> GetSolutionItems(IEnumerable <IMSBuildItem> items, ISlnGenLogger logger, Func <string, bool> fileExists) { if (items == null) { throw new ArgumentNullException(nameof(items)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (fileExists == null) { throw new ArgumentNullException(nameof(fileExists)); } foreach (string solutionItem in items.Select(i => i.GetMetadata("FullPath")).Where(i => !string.IsNullOrWhiteSpace(i))) { if (!fileExists(solutionItem)) { logger.LogMessageLow($"The solution item \"{solutionItem}\" does not exist and will not be added to the solution.", MessageImportance.Low); } else { yield return(solutionItem); } } }
/// <summary> /// Launches Visual Studio. /// </summary> /// <param name="solutionFileFullPath">The full path to the solution file.</param> /// <param name="loadProjects">A value indicating whether to load projects in Visual Studio.</param> /// <param name="devEnvFullPath">An optional full path to devenv.exe.</param> /// <param name="logger">A <see cref="ISlnGenLogger" /> to use for logging.</param> public static void Launch(string solutionFileFullPath, bool loadProjects, string devEnvFullPath, ISlnGenLogger logger) { if (solutionFileFullPath.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(solutionFileFullPath)); } CommandLineBuilder commandLineBuilder = new CommandLineBuilder(); ProcessStartInfo processStartInfo; if (!devEnvFullPath.IsNullOrWhiteSpace()) { if (!File.Exists(devEnvFullPath)) { logger.LogError($"The specified path to Visual Studio ({devEnvFullPath}) does not exist or is inaccessible."); return; } processStartInfo = new ProcessStartInfo { FileName = devEnvFullPath, UseShellExecute = false, }; commandLineBuilder.AppendFileNameIfNotNull(solutionFileFullPath); if (!loadProjects) { commandLineBuilder.AppendSwitch(DoNotLoadProjectsCommandLineArgument); } } else { processStartInfo = new ProcessStartInfo { FileName = solutionFileFullPath, UseShellExecute = true, }; } try { processStartInfo.Arguments = commandLineBuilder.ToString(); Process process = new Process { StartInfo = processStartInfo, }; logger.LogMessageHigh("Launching Visual Studio..."); logger.LogMessageLow(" FileName = {0}", processStartInfo.FileName); logger.LogMessageLow(" Arguments = {0}", processStartInfo.Arguments); logger.LogMessageLow(" UseShellExecute = {0}", processStartInfo.UseShellExecute); logger.LogMessageLow(" WindowStyle = {0}", processStartInfo.WindowStyle); if (!process.Start()) { logger.LogError("Failed to launch Visual Studio."); } } catch (Exception e) { logger.LogError($"Failed to launch Visual Studio. {e.Message}"); } }
public static void LaunchVisualStudio(string devEnvFullPath, bool useShellExecute, string solutionFileFullPath, ISlnGenLogger logger) { ProcessStartInfo processStartInfo; if (!string.IsNullOrWhiteSpace(devEnvFullPath)) { if (!File.Exists(devEnvFullPath)) { logger.LogError($"The specified path to Visual Studio ({devEnvFullPath}) does not exist or is inaccessible."); return; } processStartInfo = new ProcessStartInfo { FileName = devEnvFullPath, Arguments = $"\"{solutionFileFullPath}\"", }; } else if (!useShellExecute) { processStartInfo = new ProcessStartInfo { Arguments = $"/C start \"\" \"devenv.exe\" \"{solutionFileFullPath}\"", FileName = Environment.GetEnvironmentVariable("ComSpec"), WindowStyle = ProcessWindowStyle.Hidden, }; } else { processStartInfo = new ProcessStartInfo { FileName = solutionFileFullPath, UseShellExecute = true, }; } try { Process process = new Process { StartInfo = processStartInfo, }; logger.LogMessageHigh("Opening Visual Studio solution..."); logger.LogMessageLow(" FileName = {0}", processStartInfo.FileName); logger.LogMessageLow(" Arguments = {0}", processStartInfo.Arguments); logger.LogMessageLow(" UseShellExecute = {0}", processStartInfo.UseShellExecute); logger.LogMessageLow(" WindowStyle = {0}", processStartInfo.WindowStyle); if (!process.Start()) { logger.LogError("Failed to launch Visual Studio."); } } catch (Exception e) { logger.LogError($"Failed to launch Visual Studio. {e.Message}"); } }
/// <summary> /// Launches Visual Studio. /// </summary> /// <param name="arguments">The current <see cref="ProgramArguments" />.</param> /// <param name="visualStudioInstance">A <see cref="VisualStudioInstance" /> object representing which instance of Visual Studio to launch.</param> /// <param name="solutionFileFullPath">The full path to the solution file.</param> /// <param name="logger">A <see cref="ISlnGenLogger" /> to use for logging.</param> /// <returns>true if Visual Studio was launched, otherwise false.</returns> public static bool TryLaunch(ProgramArguments arguments, VisualStudioInstance visualStudioInstance, string solutionFileFullPath, ISlnGenLogger logger) { if (!arguments.ShouldLaunchVisualStudio()) { return(true); } if (!Utility.RunningOnWindows) { logger.LogWarning("Launching Visual Studio is not currently supported on your operating system."); return(true); } bool loadProjectsInVisualStudio = arguments.ShouldLoadProjectsInVisualStudio(); bool enableShellExecute = arguments.EnableShellExecute(); string devEnvFullPath = arguments.DevEnvFullPath?.LastOrDefault(); if (!enableShellExecute || !loadProjectsInVisualStudio || Program.CurrentDevelopmentEnvironment.IsCorext) { if (devEnvFullPath.IsNullOrWhiteSpace()) { if (visualStudioInstance == null) { logger.LogError( Program.CurrentDevelopmentEnvironment.IsCorext ? $"Could not find a Visual Studio {Environment.GetEnvironmentVariable("VisualStudioVersion")} installation. Please do one of the following:\n a) Specify a full path to devenv.exe via the -vs command-line argument\n b) Update your corext.config to specify a version of MSBuild.Corext that matches a Visual Studio version you have installed\n c) Install a version of Visual Studio that matches the version of MSBuild.Corext in your corext.config" : "Could not find a Visual Studio installation. Please specify the full path to devenv.exe via the -vs command-line argument"); return(false); } if (visualStudioInstance.IsBuildTools) { logger.LogError("Cannot use a BuildTools instance of Visual Studio."); return(false); } devEnvFullPath = Path.Combine(visualStudioInstance.InstallationPath, "Common7", "IDE", "devenv.exe"); } } if (solutionFileFullPath.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(solutionFileFullPath)); } CommandLineBuilder commandLineBuilder = new CommandLineBuilder(); ProcessStartInfo processStartInfo; if (!devEnvFullPath.IsNullOrWhiteSpace()) { if (!File.Exists(devEnvFullPath)) { logger.LogError($"The specified path to Visual Studio ({devEnvFullPath}) does not exist or is inaccessible."); return(false); } processStartInfo = new ProcessStartInfo { FileName = devEnvFullPath !, UseShellExecute = false, }; commandLineBuilder.AppendFileNameIfNotNull(solutionFileFullPath); if (!arguments.ShouldLoadProjectsInVisualStudio()) { commandLineBuilder.AppendSwitch(DoNotLoadProjectsCommandLineArgument); } } else { processStartInfo = new ProcessStartInfo { FileName = solutionFileFullPath, UseShellExecute = true, }; } try { processStartInfo.Arguments = commandLineBuilder.ToString(); Process process = new Process { StartInfo = processStartInfo, }; logger.LogMessageHigh("Launching Visual Studio..."); logger.LogMessageLow(" FileName = {0}", processStartInfo.FileName); logger.LogMessageLow(" Arguments = {0}", processStartInfo.Arguments); logger.LogMessageLow(" UseShellExecute = {0}", processStartInfo.UseShellExecute); logger.LogMessageLow(" WindowStyle = {0}", processStartInfo.WindowStyle); if (!process.Start()) { logger.LogError("Failed to launch Visual Studio."); } } catch (Exception e) { logger.LogError($"Failed to launch Visual Studio. {e.Message}"); } return(true); }
/// <summary> /// Gets the solution items' full paths. /// </summary> /// <param name="items">The <see cref="IEnumerable{IMSBuildItem}" /> containing the solution items.</param> /// <param name="logger">A <see cref="ISlnGenLogger" /> to use for logging.</param> /// <returns>An <see cref="IEnumerable{String}"/> of full paths to include as solution items.</returns> public static IEnumerable <string> GetSolutionItems(IEnumerable <IMSBuildItem> items, ISlnGenLogger logger) { return(GetSolutionItems(items, logger, File.Exists)); }
/// <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); solution.Save(solutionFileFullPath, arguments.EnableFolders(), arguments.EnableCollapseFolders()); return(solutionFileFullPath, customProjectTypeGuids.Count, solutionItems.Count, solution.SolutionGuid); }
/// <summary> /// Creates an appropriate instance of a class that implements <see cref="IProjectLoader" />. /// </summary> /// <param name="msbuildExePath">The full path to MSBuild.exe.</param> /// <param name="logger">An <see cref="ISlnGenLogger" /> object to use for logging.</param> /// <returns>An <see cref="IProjectLoader" /> object that can be used to load MSBuild projects.</returns> private static IProjectLoader Create(FileInfo msbuildExePath, ISlnGenLogger logger)
/// <summary> /// Initializes a new instance of the <see cref="ProjectGraphProjectLoader"/> class. /// </summary> /// <param name="logger">An <see cref="ISlnGenLogger" /> to use for logging.</param> public ProjectGraphProjectLoader(ISlnGenLogger logger) { _logger = logger; }
/// <summary> /// Launches Visual Studio. /// </summary> /// <param name="arguments">The current <see cref="ProgramArguments" />.</param> /// <param name="visualStudioInstance">A <see cref="VisualStudioInstance" /> object representing which instance of Visual Studio to launch.</param> /// <param name="solutionFileFullPath">The full path to the solution file.</param> /// <param name="logger">A <see cref="ISlnGenLogger" /> to use for logging.</param> /// <returns>true if Visual Studio was launched, otherwise false.</returns> public static bool TryLaunch(ProgramArguments arguments, VisualStudioInstance visualStudioInstance, string solutionFileFullPath, ISlnGenLogger logger) { if (!arguments.ShouldLaunchVisualStudio()) { return(true); } if (!Utility.RunningOnWindows) { logger.LogWarning("Launching Visual Studio is not currently supported on your operating system."); return(true); } string devEnvFullPath = arguments.GetDevEnvFullPath(visualStudioInstance); if (!devEnvFullPath.IsNullOrWhiteSpace()) { visualStudioInstance = VisualStudioConfiguration.GetInstanceForPath(devEnvFullPath); } if (visualStudioInstance == null) { logger.LogError( Program.CurrentDevelopmentEnvironment.IsCorext ? $"Could not find a Visual Studio {Environment.GetEnvironmentVariable("VisualStudioVersion")} installation. Please do one of the following:\n a) Specify a full path to devenv.exe via the -vs command-line argument\n b) Update your corext.config to specify a version of MSBuild.Corext that matches a Visual Studio version you have installed\n c) Install a version of Visual Studio that matches the version of MSBuild.Corext in your corext.config" : "Could not find a Visual Studio installation. Please run from a command window that has MSBuild.exe on the PATH or specify the full path to devenv.exe via the -vs command-line argument"); return(false); } if (visualStudioInstance.IsBuildTools) { logger.LogError("Cannot use a BuildTools instance of Visual Studio."); return(false); } if (!File.Exists(devEnvFullPath)) { logger.LogError($"The specified path to Visual Studio ({devEnvFullPath}) does not exist or is inaccessible."); return(false); } CommandLineBuilder commandLineBuilder = new CommandLineBuilder(); commandLineBuilder.AppendFileNameIfNotNull(solutionFileFullPath); if (!arguments.ShouldLoadProjectsInVisualStudio()) { commandLineBuilder.AppendSwitch(DoNotLoadProjectsCommandLineArgument); } try { Process process = new Process { StartInfo = new ProcessStartInfo { FileName = devEnvFullPath, Arguments = commandLineBuilder.ToString(), UseShellExecute = false, }, }; logger.LogMessageHigh("Launching Visual Studio..."); logger.LogMessageLow(" FileName = {0}", process.StartInfo.FileName); logger.LogMessageLow(" Arguments = {0}", process.StartInfo.Arguments); if (!process.Start()) { logger.LogError("Failed to launch Visual Studio."); } } catch (Exception e) { logger.LogError($"Failed to launch Visual Studio. {e.Message}"); } return(true); }