I created a blank solution, added a project, and then edited the configurations in the solution and in the project to add a 'Sln' and a 'Proj' prefix, respectively. The solution has 'SlnDebug' and 'SlnRelease'. The project has 'ProjDebug' and 'ProjRelease'.
This yields the following SLN file:
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32929.385
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Project", "Project\Project.csproj", "{6056F2E8-3ED1-4992-92B6-2BD1D721F940}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
SlnDebug|Any CPU = SlnDebug|Any CPU
SlnRelease|Any CPU = SlnRelease|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnDebug|Any CPU.ActiveCfg = ProjDebug|Any CPU
{6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnDebug|Any CPU.Build.0 = ProjDebug|Any CPU
{6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnRelease|Any CPU.ActiveCfg = ProjDebug|Any CPU
{6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnRelease|Any CPU.Build.0 = ProjDebug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C9B115D6-91A4-4330-B2C6-8BDCA08881F0}
EndGlobalSection
EndGlobal
The following lines map the solution's Configuration|Platform of 'SlnDebug|Any CPU' to the project's Configuration|Platform of 'ProjDebug|Any CPU'.
{6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnDebug|Any CPU.ActiveCfg = ProjDebug|Any CPU
{6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnDebug|Any CPU.Build.0 = ProjDebug|Any CPU
Using this SLN file as a test file will help to understand what SolutionFile.Parse(string solutionFile)
is doing. Also see "Solution (.sln) file" for documentation on the file format.
The following code example parses a solution file and compares the solution level and project level Configuration and Platform values.
using Microsoft.Build.Construction;
const string slnFilePath = @"<test solution file path and name>";
var solution = SolutionFile.Parse(slnFilePath);
foreach (var project in solution.ProjectsInOrder)
{
Console.WriteLine($"Project '{project.ProjectName}'");
foreach (var pair in project.ProjectConfigurations)
{
Console.WriteLine($" Solution Configuration|Platform '{pair.Key}'");
var (slnConfiguration, slnPlatform) = pair.Key.Split('|', 2, StringSplitOptions.TrimEntries) switch { var strs => (strs[0], strs[1]) };
var projConfiguration = pair.Value.ConfigurationName;
var projPlatform = pair.Value.PlatformName;
Console.WriteLine($" '{slnConfiguration}' {(slnConfiguration == projConfiguration ? "matches" : "does not match") } '{projConfiguration}'.");
// Special case for 'Any CPU' and 'AnyCPU'.
if (slnPlatform == "Any CPU" && projPlatform == "AnyCPU")
{
Console.WriteLine($" '{slnPlatform}' matches '{projPlatform}'.");
}
else
{
Console.WriteLine($" '{slnPlatform}' {(slnPlatform == projPlatform ? "matches" : "does not match")} '{projPlatform}'.");
}
}
}
Note the special case for 'Any CPU'. For legacy reasons, solutions use 'Any CPU' (with a space) and projects use 'AnyCPU' (with no space) and this should be treated as a matching platform.
This example code is intended to illustrate how the SolutionFile
object returned by Parse()
can be used and hopefully this makes the mapping clearer.