in src/Microsoft.VisualStudio.SlnGen/SlnFile.cs [386:538]
internal void Save(string rootPath, TextWriter writer, bool useFolders, bool collapseFolders = false)
{
writer.WriteLine(Header, _fileFormatVersion);
if (VisualStudioVersion != null)
{
writer.WriteLine($"# Visual Studio Version {VisualStudioVersion.Major}");
writer.WriteLine($"VisualStudioVersion = {VisualStudioVersion}");
writer.WriteLine($"MinimumVisualStudioVersion = {MinumumVisualStudioVersion}");
}
if (SolutionItems.Count > 0)
{
writer.WriteLine($@"Project(""{SlnFolder.FolderProjectTypeGuidString}"") = ""Solution Items"", ""Solution Items"", ""{{B283EBC2-E01F-412D-9339-FD56EF114549}}"" ");
writer.WriteLine(" ProjectSection(SolutionItems) = preProject");
foreach (string solutionItem in SolutionItems.Select(i => i.ToRelativePath(rootPath).ToSolutionPath()))
{
writer.WriteLine($" {solutionItem} = {solutionItem}");
}
writer.WriteLine(" EndProjectSection");
writer.WriteLine("EndProject");
}
List<SlnProject> sortedProjects = _projects.OrderBy(i => i.IsMainProject ? 0 : 1).ThenBy(i => i.FullPath).ToList();
foreach (SlnProject project in sortedProjects)
{
string solutionPath = project.FullPath.ToRelativePath(rootPath).ToSolutionPath();
if (ExistingProjectGuids != null && ExistingProjectGuids.TryGetValue(solutionPath, out Guid existingProjectGuid))
{
project.ProjectGuid = existingProjectGuid;
}
writer.WriteLine($@"Project(""{project.ProjectTypeGuid.ToSolutionString()}"") = ""{project.Name}"", ""{solutionPath}"", ""{project.ProjectGuid.ToSolutionString()}""");
writer.WriteLine("EndProject");
}
SlnHierarchy hierarchy = null;
if (useFolders && sortedProjects.Any(i => !i.IsMainProject))
{
hierarchy = SlnHierarchy.CreateFromProjectDirectories(sortedProjects, collapseFolders);
}
else if (sortedProjects.Any(i => !string.IsNullOrWhiteSpace(i.SolutionFolder)))
{
hierarchy = SlnHierarchy.CreateFromProjectSolutionFolder(sortedProjects);
}
if (hierarchy != null)
{
foreach (SlnFolder folder in hierarchy.Folders)
{
string projectSolutionPath = (useFolders ? folder.FullPath.ToRelativePath(rootPath) : folder.Name).ToSolutionPath();
// Try to preserve the folder GUID if a matching relative folder path was parsed from an existing solution
if (ExistingProjectGuids != null && ExistingProjectGuids.TryGetValue(projectSolutionPath, out Guid projectGuid))
{
folder.FolderGuid = projectGuid;
}
writer.WriteLine($@"Project(""{folder.ProjectTypeGuidString}"") = ""{folder.Name}"", ""{projectSolutionPath}"", ""{folder.FolderGuid.ToSolutionString()}""");
writer.WriteLine("EndProject");
}
}
writer.WriteLine("Global");
writer.WriteLine(" GlobalSection(SolutionConfigurationPlatforms) = preSolution");
HashSet<string> solutionPlatforms = Platforms != null && Platforms.Any()
? new HashSet<string>(GetValidSolutionPlatforms(Platforms), StringComparer.OrdinalIgnoreCase)
: new HashSet<string>(GetValidSolutionPlatforms(sortedProjects.SelectMany(i => i.Platforms)), StringComparer.OrdinalIgnoreCase);
HashSet<string> solutionConfigurations = Configurations != null && Configurations.Any()
? new HashSet<string>(Configurations, StringComparer.OrdinalIgnoreCase)
: new HashSet<string>(sortedProjects.SelectMany(i => i.Configurations).Where(i => !i.IsNullOrWhiteSpace()), StringComparer.OrdinalIgnoreCase);
foreach (string configuration in solutionConfigurations)
{
foreach (string platform in solutionPlatforms)
{
if (!string.IsNullOrWhiteSpace(configuration) && !string.IsNullOrWhiteSpace(platform))
{
writer.WriteLine($" {configuration}|{platform} = {configuration}|{platform}");
}
}
}
writer.WriteLine(" EndGlobalSection");
writer.WriteLine(" GlobalSection(ProjectConfigurationPlatforms) = postSolution");
foreach (SlnProject project in sortedProjects)
{
string projectGuid = project.ProjectGuid.ToSolutionString();
foreach (string configuration in solutionConfigurations)
{
bool foundConfiguration = TryGetProjectSolutionConfiguration(configuration, project, out string projectSolutionConfiguration);
foreach (string platform in solutionPlatforms)
{
bool foundPlatform = TryGetProjectSolutionPlatform(platform, project, out string projectSolutionPlatform, out string projectBuildPlatform);
writer.WriteLine($@" {projectGuid}.{configuration}|{platform}.ActiveCfg = {projectSolutionConfiguration}|{projectSolutionPlatform}");
if (foundPlatform && foundConfiguration)
{
writer.WriteLine($@" {projectGuid}.{configuration}|{platform}.Build.0 = {projectSolutionConfiguration}|{projectBuildPlatform}");
}
if (project.IsDeployable)
{
writer.WriteLine($@" {projectGuid}.{configuration}|{platform}.Deploy.0 = {projectSolutionConfiguration}|{projectSolutionPlatform}");
}
}
}
}
writer.WriteLine(" EndGlobalSection");
writer.WriteLine(" GlobalSection(SolutionProperties) = preSolution");
writer.WriteLine(" HideSolutionNode = FALSE");
writer.WriteLine(" EndGlobalSection");
if (hierarchy != null)
{
writer.WriteLine(@" GlobalSection(NestedProjects) = preSolution");
foreach (SlnFolder folder in hierarchy.Folders.Where(i => i.Parent != null))
{
foreach (SlnProject project in folder.Projects)
{
writer.WriteLine($@" {project.ProjectGuid.ToSolutionString()} = {folder.FolderGuid.ToSolutionString()}");
}
if (useFolders)
{
writer.WriteLine($@" {folder.FolderGuid.ToSolutionString()} = {folder.Parent.FolderGuid.ToSolutionString()}");
}
}
writer.WriteLine(" EndGlobalSection");
}
writer.WriteLine(" GlobalSection(ExtensibilityGlobals) = postSolution");
writer.WriteLine($" SolutionGuid = {SolutionGuid.ToSolutionString()}");
writer.WriteLine(" EndGlobalSection");
writer.WriteLine("EndGlobal");
}