Questions Related with .slnFile

64 views Asked by At

Question 1: is the format of default solution file of c# ProjectText always same?

Project(Solution GUI) = SolutionName , ProjectPath, csProjPath, ProjectGUI

e.g:

Project("{FAE14EC0-321D-12D3-GF35-01C04F79EFBC}") = "WindowsFormsApplication26", "WindowsFormsApplication26\WindowsFormsApplication26.csproj", "{25F0453B-9C88-4C9E-AG6A-97873BB6EA23}"
EndProject

same format as: 1st it will have Solution GUI then solutionName then csproj path then projectGUI

Question 2: i have created a regex to get the Text generated by .sln and here's what i've got:

Regex projectRegex = new Regex(@"Project\(\""([^\""]+)\""\)\s*\=\s*\""([^\""]+)\""\,\s*\""([^\""]+)""\,\s*\""([^\""]+)""");

but im not sure if there's a possible bug in my regex related with the first question, so im thinking if theres a better regex or any condition (e.g parse or any that must be faster) to get the ProjectText specifically (what i need to get) was the csProj path (which is on regex pattern above on Group3)

and for the group applied on example shown on Q1:

Group1: {FAE14EC0-321D-12D3-GF35-01C04F79EFBC}
Group2: WindowsFormsApplication26
Group3: WindowsFormsApplication26\WindowsFormsApplication26.csproj
Group4: {25F0453B-9C88-4C9E-AG6A-97873BB6EA23}
1

There are 1 answers

7
Fratyx On BEST ANSWER

I think your way should by working correctly but for extracting information from solution files we use the following method by accessing the internal technique of the 'Microsoft.Build' namespace. As the corresponding framework functions are marked as internal, it is necessary to 'hack' them. Therefore the complicated way using reflection. (It's a condensed extract from other code snippets we found in internet - also in SO)

public struct ProjectData
{
    public string Name;
    public string Guid;
    public string Path;
}

public static List<ProjectData> GetProjectsInSolution(string pathToSolutionFile)
{
    Type parserType = Type.GetType("Microsoft.Build.Construction.SolutionParser, Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", false, false);

    ConstructorInfo constructorInfo = parserType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).First();
    object solutionParser = constructorInfo.Invoke(null);

    PropertyInfo solutionFileProperty = parserType.GetProperty("SolutionFile", BindingFlags.NonPublic | BindingFlags.Instance);
    solutionFileProperty.SetValue(solutionParser, pathToSolutionFile);

    MethodInfo parserMethod = parserType.GetMethod("ParseSolutionFile", BindingFlags.NonPublic | BindingFlags.Instance);
    parserMethod.Invoke(solutionParser, null);

    PropertyInfo projectInfo = parserType.GetProperty("Projects", BindingFlags.NonPublic | BindingFlags.Instance);
    object[] projects = projectInfo.GetValue(solutionParser) as object[];

    Type projectType = Type.GetType("Microsoft.Build.Construction.ProjectInSolution, Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", false, false);

    PropertyInfo nameInfo = projectType.GetProperty("ProjectName", BindingFlags.NonPublic | BindingFlags.Instance);
    PropertyInfo guidInfo = projectType.GetProperty("ProjectGuid", BindingFlags.NonPublic | BindingFlags.Instance);
    PropertyInfo pathInfo = projectType.GetProperty("RelativePath", BindingFlags.NonPublic | BindingFlags.Instance);

    List<ProjectData> projectData = new List<ProjectData>();

    if (projects != null)
    {
        foreach (object project in projects)
        {
            projectData.Add(new ProjectData()
            {
                Name = nameInfo.GetValue(project) as string,
                Guid = guidInfo.GetValue(project) as string,
                Path = pathInfo.GetValue(project) as string
            });
        }
    }

    return projectData;
}