public ProjectProcessorContext(Solution solution, Project project, XDocument document, XmlNamespaceManager namespaceManager) { Solution = solution; Project = project; Document = document; NamespaceManager = namespaceManager; }
/// <summary> /// Initializes a new instance of the <see cref="Project"/> class. /// </summary> /// <param name="solution">The solution.</param> /// <param name="guid">The unique identifier.</param> /// <param name="typeGuid">The type unique identifier.</param> /// <param name="name">The name.</param> /// <param name="relativePath">The relative path.</param> /// <param name="parentGuid">The parent unique identifier.</param> /// <param name="projectSections">The project sections.</param> /// <param name="versionControlLines">The version control lines.</param> /// <param name="projectConfigurationPlatformsLines">The project configuration platforms lines.</param> /// <exception cref="System.ArgumentNullException"> /// solution /// or /// guid /// or /// typeGuid /// or /// name /// </exception> public Project( Solution solution, Guid guid, Guid typeGuid, string name, string relativePath, Guid parentGuid, IEnumerable<Section> projectSections, IEnumerable<PropertyItem> versionControlLines, IEnumerable<PropertyItem> projectConfigurationPlatformsLines) { if (solution == null) throw new ArgumentNullException("solution"); if (guid == null) throw new ArgumentNullException("guid"); if (typeGuid == null) throw new ArgumentNullException("typeGuid"); if (name == null) throw new ArgumentNullException("name"); this.solution = solution; this.guid = guid; this.TypeGuid = typeGuid; this.Name = name; this.RelativePath = relativePath; this.ParentGuid = parentGuid; sections = new SectionCollection(projectSections); versionControlProperties = new PropertyItemCollection(versionControlLines); platformProperties = new PropertyItemCollection(projectConfigurationPlatformsLines); }
private void WriteGlobalSections(Solution solution) { foreach (Section globalSection in solution.GlobalSections) { var propertyLines = new List<PropertyItem>(globalSection.Properties); switch (globalSection.Name) { case "NestedProjects": foreach (Project project in solution.Projects) { if (project.ParentGuid != Guid.Empty) { propertyLines.Add(new PropertyItem(project.Guid.ToString("B").ToUpperInvariant(), project.ParentGuid.ToString("B").ToUpperInvariant())); } } break; case "ProjectConfigurationPlatforms": foreach (Project project in solution.Projects) { foreach (PropertyItem propertyLine in project.PlatformProperties) { propertyLines.Add( new PropertyItem( string.Format("{0}.{1}", project.Guid.ToString("B").ToUpperInvariant(), propertyLine.Name), propertyLine.Value)); } } break; default: if (globalSection.Name.EndsWith("Control", StringComparison.InvariantCultureIgnoreCase)) { int index = 1; foreach (Project project in solution.Projects) { if (project.VersionControlProperties.Count > 0) { foreach (PropertyItem propertyLine in project.VersionControlProperties) { propertyLines.Add( new PropertyItem( string.Format("{0}{1}", propertyLine.Name, index), propertyLine.Value)); } index++; } } propertyLines.Insert(0, new PropertyItem("SccNumberOfProjects", index.ToString())); } break; } WriteSection(globalSection, propertyLines); } }
public void WriteSolutionFile(Solution solution) { lock (writer) { WriteHeader(solution); WriteProjects(solution); WriteGlobal(solution); } }
/// <summary> /// Initializes a new instance of the <see cref="Project"/> class. /// </summary> /// <param name="solution">The solution.</param> /// <param name="original">The original.</param> public Project(Solution solution, Project original) : this( solution, original.Guid, original.TypeGuid, original.Name, original.RelativePath, original.ParentGuid, original.Sections, original.VersionControlProperties, original.PlatformProperties) { }
public Solution ReadSolutionFile() { lock (reader) { solution = new Solution(); ReadHeader(); for (string line = ReadLine(); line != null; line = ReadLine()) { // Skip blank lines if (string.IsNullOrWhiteSpace(line)) { continue; } if (line.StartsWith("Project(", StringComparison.InvariantCultureIgnoreCase)) { solution.Projects.Add(ReadProject(line)); } else if (String.Compare(line, "Global", StringComparison.InvariantCultureIgnoreCase) == 0) { ReadGlobal(); // TODO valide end of file break; } else if (RegexParsePropertyLine.Match(line).Success) { // Read VS properties (introduced in VS2012/VS2013?) solution.Properties.Add(ReadPropertyLine(line)); } else { throw new SolutionFileException(string.Format("Invalid line read on line #{0}.\nFound: {1}\nExpected: A line beginning with 'Project(' or 'Global'.", currentLineNumber, line)); } } return solution; } }
public static void SaveSolution(PackageSession session, ILogger log) { // If the solution path is not set, we can't save a solution (sln) if (session.SolutionPath == null) { return; } var solutionPath = UPath.Combine(Environment.CurrentDirectory, session.SolutionPath); try { Solution solution; var solutionDir = solutionPath.GetParent(); // If the solution already exists, we need to update it if (File.Exists(solutionPath)) { solution = Solution.FromFile(solutionPath); } else { solution = new Solution { FullPath = solutionPath }; solution.Headers.Add(SolutionHeader); } // Pre-create solution wide global sections if (!solution.GlobalSections.Contains("SolutionConfigurationPlatforms")) { solution.GlobalSections.Add(new Section("SolutionConfigurationPlatforms", "GlobalSection", "preSolution", Enumerable.Empty<PropertyItem>())); } if (!solution.GlobalSections.Contains("ProjectConfigurationPlatforms")) { solution.GlobalSections.Add(new Section("ProjectConfigurationPlatforms", "GlobalSection", "postSolution", Enumerable.Empty<PropertyItem>())); } if (!solution.GlobalSections.Contains("NestedProjects")) { solution.GlobalSections.Add(new Section("NestedProjects", "GlobalSection", "preSolution", Enumerable.Empty<PropertyItem>())); } // --------------------------------------------- // 0. Pre-select only platforms effectively used by this session // --------------------------------------------- var platformsUsedBySession = new SolutionPlatformCollection(); platformsUsedBySession.AddRange(AssetRegistry.SupportedPlatforms.Where(platform => platform.Type == PlatformType.Windows)); foreach (var package in session.LocalPackages) { foreach (var profile in package.Profiles.Where(profile => profile.Platform != PlatformType.Shared && profile.ProjectReferences.Count > 0)) { var platformType = profile.Platform; if (!platformsUsedBySession.Contains(platformType)) { platformsUsedBySession.AddRange(AssetRegistry.SupportedPlatforms.Where(platform => platform.Type == platformType)); } } } // --------------------------------------------- // 1. Update configuration/platform // --------------------------------------------- var configs = new List<Tuple<string, SolutionPlatform, SolutionPlatformPart>>(); foreach (var configName in platformsUsedBySession.SelectMany(solutionPlatform => solutionPlatform.Configurations).Select(config => config.Name).Distinct()) { foreach (var platform in platformsUsedBySession) { foreach (var platformPart in platform.GetParts()) { // Skip platforms with IncludeInSolution == false if (!platformPart.IncludeInSolution) continue; configs.Add(new Tuple<string, SolutionPlatform, SolutionPlatformPart>(configName, platform, platformPart)); } } } // Order per config and then per platform names configs = configs.OrderBy(part => part.Item1, StringComparer.InvariantCultureIgnoreCase).ThenBy(part => part.Item3.SafeSolutionName, StringComparer.InvariantCultureIgnoreCase).ToList(); // Write configs in alphabetical order to avoid changes in sln after it is generated var solutionPlatforms = solution.GlobalSections["SolutionConfigurationPlatforms"]; solutionPlatforms.Properties.Clear(); foreach (var config in configs) { var solutionConfigPlatform = string.Format("{0}|{1}", config.Item1, config.Item3.SafeSolutionName); if (!solutionPlatforms.Properties.Contains(solutionConfigPlatform)) { solutionPlatforms.Properties.Add(new PropertyItem(solutionConfigPlatform, solutionConfigPlatform)); } } // Remove projects that are no longer available on the disk var projectToRemove = solution.Projects.Where(project => !project.IsSolutionFolder && !File.Exists(project.FullPath)).ToList(); foreach (var project in projectToRemove) { solution.Projects.Remove(project); } // --------------------------------------------- // 2. Update each package // --------------------------------------------- foreach (var package in session.LocalPackages) { if (string.IsNullOrWhiteSpace(package.Meta.Name)) { log.Error("Error while saving solution [{0}]. Package [{1}] should have a Meta.Name", solutionPath, package.FullPath); continue; } var packageFolder = solution.Projects.FindByGuid(package.Id); // Packages are created as solution folders in VisualStudio if (packageFolder == null) { // Create this package as a Solution Folder packageFolder = new Project(solution, package.Id, KnownProjectTypeGuid.SolutionFolder, package.Meta.Name, package.Meta.Name, Guid.Empty, Enumerable.Empty<Section>(), Enumerable.Empty<PropertyItem>(), Enumerable.Empty<PropertyItem>()); // As it is making a copy, we need to get it back solution.Projects.Add(packageFolder); packageFolder = solution.Projects[package.Id]; } // Update the path to the solution everytime we save a package packageFolder.Sections.Clear(); var relativeUrl = package.FullPath.MakeRelative(solutionDir); packageFolder.Sections.Add(new Section(SiliconStudioPackage, "ProjectSection", "preProject", new[] { new PropertyItem(relativeUrl, relativeUrl) })); // --------------------------------------------- // 2.1. Update each project // --------------------------------------------- foreach (var profile in package.Profiles.OrderBy(x => x.Platform == PlatformType.Windows ? 0 : 1)) { foreach (var project in profile.ProjectReferences) { var projectInSolution = solution.Projects.FindByGuid(project.Id); if (projectInSolution == null) { var projectRelativePath = project.Location.MakeRelative(solutionDir); // Create this package as a Solution Folder projectInSolution = new Project(solution, project.Id, KnownProjectTypeGuid.CSharp, project.Location.GetFileName(), projectRelativePath.ToWindowsPath(), package.Id, Enumerable.Empty<Section>(), Enumerable.Empty<PropertyItem>(), Enumerable.Empty<PropertyItem>()); solution.Projects.Add(projectInSolution); // Resolve it again, as the original code is making a clone of it (why?) projectInSolution = solution.Projects.FindByGuid(project.Id); } // Projects are always in a package (solution folder) in the solution projectInSolution.ParentGuid = package.Id; // Update platforms per project (active solution and build flag per platform) // Clear all platform properties for this project and recompute them here projectInSolution.PlatformProperties.Clear(); foreach (var config in configs) { var configName = config.Item1; var platform = config.Item2; var platformPart = config.Item3; // Filter exe project types if (project.Type == ProjectType.Executable && !platformPart.UseWithExecutables) { continue; } var platformName = platformPart.SafeSolutionName; var solutionConfigPlatform = string.Format("{0}|{1}", configName, platformName); var configNameInProject = configName; var platformNameInProject = platformPart.GetProjectName(project.Type); var platformTarget = platform; if (profile.Platform != PlatformType.Shared) { platformTarget = platformsUsedBySession.First(plat => plat.Type == profile.Platform); } bool isPartOfBuild = platformTarget == platform; // If the config doesn't exist for this platform, just use the default config name if (!platformTarget.Configurations.Contains(configName)) { configNameInProject = platformTarget.Configurations.FirstOrDefault().Name; isPartOfBuild = false; } // If the config doesn't exist for this platform, just use the default config name if (platformTarget.GetParts().All(part => part.GetProjectName(project.Type) != platformNameInProject)) { platformNameInProject = platformTarget.GetParts().FirstOrDefault(part => part.IsProjectHandled(project.Type)).SafeSolutionName; isPartOfBuild = false; } var projectConfigPlatform = string.Format("{0}|{1}", configNameInProject, platformNameInProject); var propertyActive = solutionConfigPlatform + ".ActiveCfg"; var propertyBuild = solutionConfigPlatform + ".Build.0"; if (!projectInSolution.PlatformProperties.Contains(propertyActive)) { projectInSolution.PlatformProperties.Remove(propertyActive); projectInSolution.PlatformProperties.Add(new PropertyItem(propertyActive, projectConfigPlatform)); } // Only add Build and Deploy for supported configs if (isPartOfBuild) { projectInSolution.PlatformProperties.Remove(propertyBuild); projectInSolution.PlatformProperties.Add(new PropertyItem(propertyBuild, projectConfigPlatform)); // If the project is an executable, mark it as deploy if (project.Type == ProjectType.Executable) { var propertyDeploy = solutionConfigPlatform + ".Deploy.0"; projectInSolution.PlatformProperties.Remove(propertyDeploy); projectInSolution.PlatformProperties.Add(new PropertyItem(propertyDeploy, projectConfigPlatform)); } } } } } // --------------------------------------------- // 3. Remove unused packages from the solution // --------------------------------------------- for (int i = solution.Projects.Count - 1; i >=0; i--) { var project = solution.Projects[i]; if (IsPackage(project) && !session.Packages.ContainsById(project.Guid)) { solution.Projects.RemoveAt(i); } } } solution.Save(); } catch (Exception ex) { log.Error("Error while saving solution [{0}]", ex, solutionPath); } }
/// <summary> /// Updates the solution build configurations. /// </summary> /// <param name="platform">The platform.</param> /// <param name="solution">The solution.</param> /// <param name="projectProcessorContexts">The project processor contexts.</param> private static void UpdateSolutionBuildConfigurations(string platform, Solution solution, List<ProjectProcessorContext> projectProcessorContexts) { var configurations = new Dictionary<string, string>(); bool needDeploy = false; PlatformType requestedPlatform; if (!PlatformType.TryParse(platform, out requestedPlatform)) { throw new ArgumentOutOfRangeException(nameof(platform), "Invalid platform specified"); } switch (requestedPlatform) { case PlatformType.Windows: // Nothing to do here. break; case PlatformType.WindowsPhone: case PlatformType.WindowsStore: case PlatformType.Android: configurations.Add(platform, platform); needDeploy = true; break; case PlatformType.Linux: case PlatformType.Windows10: configurations.Add(platform, "Any CPU"); needDeploy = true; break; case PlatformType.iOS: configurations.Add("iPhone", "iPhone"); configurations.Add("iPhoneSimulator", "iPhoneSimulator"); needDeploy = true; break; default: throw new InvalidOperationException("Unknown platform " + requestedPlatform); } // Remove any reference of shared projects in the GlobalSections. var projects = solution.GlobalSections.FirstOrDefault(s => s.Name == "SharedMSBuildProjectFiles"); if (projects != null) { List<PropertyItem> toRemove = new List<PropertyItem>(); foreach (var projRef in projects.Properties) { // We assume here that we do not have the same project name in 2 or more locations var splitted = projRef.Name.Split('*'); if (splitted.Length >= 2) { Guid guid; if (Guid.TryParse(splitted[1], out guid) && !solution.Projects.Contains(guid)) { toRemove.Add(projRef); } } } foreach (var projRef in toRemove) { projects.Properties.Remove(projRef); } } // Update .sln for build configurations if (configurations.Count > 0) { var regex = new Regex(@"^(.*)\|((.*?)(?:\.(.*))?)$"); var solutionConfigurations = solution.GlobalSections["SolutionConfigurationPlatforms"].Properties .Select(x => Tuple.Create(x, regex.Match(x.Name), regex.Match(x.Value))) .ToArray(); solution.GlobalSections["SolutionConfigurationPlatforms"].Properties.Clear(); // Generate solution configurations foreach (var solutionConfiguration in solutionConfigurations) { var name = solutionConfiguration.Item2; var value = solutionConfiguration.Item3; foreach (var configuration in configurations) { solution.GlobalSections["SolutionConfigurationPlatforms"].Properties.Add( new PropertyItem(name.Groups[1].Value + "|" + configuration.Key, value.Groups[1] + "|" + configuration.Key)); } } // Generate project configurations foreach (var context in projectProcessorContexts) { // Check if platform is forced (in which case configuration line value should be kept as is) var siliconStudioPlatformNode = context.Document.XPathSelectElement("/x:Project/x:PropertyGroup/x:SiliconStudioPlatform", context.NamespaceManager); // Keep project platform only if SiliconStudioPlatform is set manually to Windows and not a platform specific project bool keepProjectPlatform = (siliconStudioPlatformNode != null && siliconStudioPlatformNode.Value == "Windows") && !context.Modified; // Extract config, we want to parse {78A3E406-EC0E-43B8-8EF2-30D3A149FBB6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU // into: // - {78A3E406-EC0E-43B8-8EF2-30D3A149FBB6}.Debug| // - .ActiveCfg // - Debug| var projectConfigLines = context.Project.PlatformProperties .Select(x => Tuple.Create(x, regex.Match(x.Name), regex.Match(x.Value))) .ToArray(); context.Project.PlatformProperties.Clear(); var matchingProjectConfigLines = new List<Tuple<PropertyItem, Match, Match>>(); foreach (var projectConfigLine in projectConfigLines) { var name = projectConfigLine.Item2; var value = projectConfigLine.Item3; // Simply copy lines that doesn't match pattern if (!name.Success || !name.Groups[4].Success || !value.Success) { context.Project.PlatformProperties.Add(projectConfigLine.Item1); } else { matchingProjectConfigLines.Add(projectConfigLine); } } // Print configuration again foreach (var configuration in configurations) { foreach (var projectConfigLine in matchingProjectConfigLines) { var name = projectConfigLine.Item2; var value = projectConfigLine.Item3; var newName = name.Groups[1].Value + "|" + configuration.Key + "." + name.Groups[4].Value; var newValue = keepProjectPlatform ? projectConfigLine.Item1.Value : value.Groups[1] + "|" + configuration.Value; context.Project.PlatformProperties.Add(new PropertyItem(newName, newValue)); // Active Deploy in solution configuration if (needDeploy && !keepProjectPlatform && newName.EndsWith("Build.0")) { context.Project.PlatformProperties.Add(new PropertyItem(newName.Replace("Build.0", "Deploy.0"), newValue)); } } } } } }
/// <summary> /// Process each project and select the one that needs to be included. /// </summary> /// <param name="solution">The solution.</param> /// <param name="platform">The platform.</param> /// <param name="projectProcessorContexts">The project processor contexts.</param> /// <param name="removedProjects">The removed projects.</param> private static void SelectActiveProjects(Solution solution, string platform, List<ProjectProcessorContext> projectProcessorContexts, List<Project> removedProjects) { foreach (var solutionProject in solution.Projects.ToArray()) { // Is it really a project? if (!solutionProject.FullPath.EndsWith(".csproj") && !solutionProject.FullPath.EndsWith(".vcxproj") && !solutionProject.FullPath.EndsWith(".shproj")) continue; // Load XML project var doc = XDocument.Load(solutionProject.FullPath); var ns = doc.Root.Name.Namespace; var mgr = new XmlNamespaceManager(new NameTable()); mgr.AddNamespace("x", ns.NamespaceName); bool shouldKeep = false; // Check XenkoSupportedPlatforms var xenkoBuildTagsNode = doc.XPathSelectElement("/x:Project/x:PropertyGroup/x:XenkoBuildTags", mgr); if (xenkoBuildTagsNode != null) { var xenkoBuildTags = xenkoBuildTagsNode.Value; if (xenkoBuildTags == "*" || xenkoBuildTags.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Contains(platform)) shouldKeep = true; } // Windows-specific project without a platform-specific equivalent are removed. var fullPath = solutionProject.FullPath; if (Path.GetFileNameWithoutExtension(fullPath).EndsWith(".Windows")) { // Replace .Windows with current platform fullPath = fullPath.Replace(".Windows", "." + platform); if (!File.Exists(fullPath)) { shouldKeep = false; } } if (shouldKeep) { projectProcessorContexts.Add(new ProjectProcessorContext(solution, solutionProject, doc, mgr)); } else { removedProjects.Add(solutionProject); solution.Projects.Remove(solutionProject); } } }
private static void RemoveEmptySolutionFolders(Solution solution) { var usedSolutionFolders = new HashSet<Project>(); // Find projects and solution folders containing files (there is a section) var projects = solution.Projects.Where(x => !x.IsSolutionFolder || x.Sections.Count > 0).ToArray(); // Mark solution folders of projects as needed foreach (var project in projects) { var currentProject = project; // Go through parents and add them to usedSolutionFolders while (currentProject != null) { usedSolutionFolders.Add(currentProject); currentProject = currentProject.ParentProject; } } // Remove unused solution folders solution.Projects.RemoveWhere(x => !usedSolutionFolders.Contains(x)); }
/// <summary> /// Updates the solution build configurations. /// </summary> /// <param name="platform">The platform.</param> /// <param name="solution">The solution.</param> /// <param name="projectProcessorContexts">The project processor contexts.</param> private static void UpdateSolutionBuildConfigurations(string platform, Solution solution, List<ProjectProcessorContext> projectProcessorContexts) { var configurations = new Dictionary<string, string>(); bool needDeploy = false; if (platform == "WindowsPhone") { configurations.Add("WindowsPhone", "WindowsPhone"); needDeploy = true; } else if (platform == "WindowsStore") { configurations.Add("WindowsStore", "WindowsStore"); needDeploy = true; } else if (platform == "Windows10") { configurations.Add("Windows10", "Windows10"); needDeploy = true; } else if (platform == "iOS") { configurations.Add("iPhone", "iPhone"); configurations.Add("iPhoneSimulator", "iPhoneSimulator"); needDeploy = true; } else if (platform == "Android") { configurations.Add("Android", "Android"); needDeploy = true; } // Update .sln for build configurations if (configurations.Count > 0) { var regex = new Regex(@"^(.*)\|((.*?)(?:\.(.*))?)$"); var solutionConfigurations = solution.GlobalSections["SolutionConfigurationPlatforms"].Properties .Select(x => Tuple.Create(x, regex.Match(x.Name), regex.Match(x.Value))) .ToArray(); solution.GlobalSections["SolutionConfigurationPlatforms"].Properties.Clear(); // Generate solution configurations foreach (var solutionConfiguration in solutionConfigurations) { var name = solutionConfiguration.Item2; var value = solutionConfiguration.Item3; foreach (var configuration in configurations) { solution.GlobalSections["SolutionConfigurationPlatforms"].Properties.Add( new PropertyItem(name.Groups[1].Value + "|" + configuration.Key, value.Groups[1] + "|" + configuration.Key)); } } // Generate project configurations foreach (var context in projectProcessorContexts) { // Check if platform is forced (in which case configuration line value should be kept as is) var siliconStudioPlatformNode = context.Document.XPathSelectElement("/x:Project/x:PropertyGroup/x:SiliconStudioPlatform", context.NamespaceManager); // Keep project platform only if SiliconStudioPlatform is set manually to Windows and not a platform specific project bool keepProjectPlatform = (siliconStudioPlatformNode != null && siliconStudioPlatformNode.Value == "Windows") && !context.Modified; // Extract config, we want to parse {78A3E406-EC0E-43B8-8EF2-30D3A149FBB6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU // into: // - {78A3E406-EC0E-43B8-8EF2-30D3A149FBB6}.Debug| // - .ActiveCfg // - Debug| var projectConfigLines = context.Project.PlatformProperties .Select(x => Tuple.Create(x, regex.Match(x.Name), regex.Match(x.Value))) .ToArray(); context.Project.PlatformProperties.Clear(); var matchingProjectConfigLines = new List<Tuple<PropertyItem, Match, Match>>(); foreach (var projectConfigLine in projectConfigLines) { var name = projectConfigLine.Item2; var value = projectConfigLine.Item3; // Simply copy lines that doesn't match pattern if (!name.Success || !name.Groups[4].Success || !value.Success) { context.Project.PlatformProperties.Add(projectConfigLine.Item1); } else { matchingProjectConfigLines.Add(projectConfigLine); } } // Print configuration again foreach (var configuration in configurations) { foreach (var projectConfigLine in matchingProjectConfigLines) { var name = projectConfigLine.Item2; var value = projectConfigLine.Item3; var newName = name.Groups[1].Value + "|" + configuration.Key + "." + name.Groups[4].Value; var newValue = keepProjectPlatform ? projectConfigLine.Item1.Value : value.Groups[1] + "|" + configuration.Value; context.Project.PlatformProperties.Add(new PropertyItem(newName, newValue)); // Active Deploy in solution configuration if (needDeploy && !keepProjectPlatform && newName.EndsWith("Build.0")) { context.Project.PlatformProperties.Add(new PropertyItem(newName.Replace("Build.0", "Deploy.0"), newValue)); } } } } } }
private Solution(Solution original) : this(original.FullPath, original.Headers, original.Projects, original.GlobalSections, original.Properties) { }
private void WriteGlobal(Solution solution) { writer.WriteLine("Global"); WriteGlobalSections(solution); writer.WriteLine("EndGlobal"); }
private void WriteProjects(Solution solution) { foreach (Project project in solution.Projects) { writer.WriteLine("Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"", project.TypeGuid.ToString("B").ToUpperInvariant(), project.Name, project.RelativePath, project.Guid.ToString("B").ToUpperInvariant()); foreach (Section projectSection in project.Sections) { WriteSection(projectSection, projectSection.Properties); } writer.WriteLine("EndProject"); } }
private void WriteHeader(Solution solution) { // If the header doesn't start with an empty line, add one // (The first line of sln files saved as UTF-8 with BOM must be blank, otherwise Visual Studio Version Selector will not detect VS version correctly.) if (solution.Headers.Count == 0 || solution.Headers[0].Trim().Length > 0) { writer.WriteLine(); } foreach (string line in solution.Headers) { writer.WriteLine(line); } foreach (PropertyItem propertyLine in solution.Properties) { writer.WriteLine("{0} = {1}", propertyLine.Name, propertyLine.Value); } }