none
How to get the list of project types in a solution programatically RRS feed

  • Question

  • I want to get a list of different projects and their types given a solution file path. Solution might be build either in .net FW or .net core. I tried to use the msbuild api, but did not find anything that can get this to me.
    Monday, January 6, 2020 2:22 PM

Answers

  • Hi Sandeep Tammisetty,

    Welcome to MSDN forum.

    According to your requirement, you could use this sample to get project list from sln file. And since the framework version is a property in csproj file instead of sln file. So you also need to read csproj file to get the framework info. 

    The solution class:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    
    namespace GetProjectFromSolution
    {
        public class Solution
        {
            //internal class SolutionParser
            //Name: Microsoft.Build.Construction.SolutionParser
            //Assembly: Microsoft.Build, Version=4.0.0.0
    
            static readonly Type s_SolutionParser;
            static readonly PropertyInfo s_SolutionParser_solutionReader;
            static readonly MethodInfo s_SolutionParser_parseSolution;
            static readonly PropertyInfo s_SolutionParser_projects;
    
            static Solution()
            {
                s_SolutionParser = Type.GetType("Microsoft.Build.Construction.SolutionParser, Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", false, false);
                if (s_SolutionParser != null)
                {
                    s_SolutionParser_solutionReader = s_SolutionParser.GetProperty("SolutionReader", BindingFlags.NonPublic | BindingFlags.Instance);
                    s_SolutionParser_projects = s_SolutionParser.GetProperty("Projects", BindingFlags.NonPublic | BindingFlags.Instance);
                    s_SolutionParser_parseSolution = s_SolutionParser.GetMethod("ParseSolution", BindingFlags.NonPublic | BindingFlags.Instance);
                }
            }
    
            public List<SolutionProject> Projects { get; private set; }
    
            public Solution(string solutionFileName)
            {
                if (s_SolutionParser == null)
                {
                    throw new InvalidOperationException("Can not find type 'Microsoft.Build.Construction.SolutionParser' are you missing a assembly reference to 'Microsoft.Build.dll'?");
                }
                var solutionParser = s_SolutionParser.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).First().Invoke(null);
                using (var streamReader = new StreamReader(solutionFileName))
                {
                    s_SolutionParser_solutionReader.SetValue(solutionParser, streamReader, null);
                    s_SolutionParser_parseSolution.Invoke(solutionParser, null);
                }
                var projects = new List<SolutionProject>();
                var array = (Array)s_SolutionParser_projects.GetValue(solutionParser, null);
                for (int i = 0; i < array.Length; i++)
                {
                    projects.Add(new SolutionProject(array.GetValue(i)));
                }
                this.Projects = projects;
            }
        }
    
        [DebuggerDisplay("{ProjectName}, {RelativePath}, {ProjectGuid}")]
        public class SolutionProject
        {
            static readonly Type s_ProjectInSolution;
            static readonly PropertyInfo s_ProjectInSolution_ProjectName;
            static readonly PropertyInfo s_ProjectInSolution_RelativePath;
            static readonly PropertyInfo s_ProjectInSolution_ProjectGuid;
            static readonly PropertyInfo s_ProjectInSolution_ProjectType;
    
            static SolutionProject()
            {
                s_ProjectInSolution = Type.GetType("Microsoft.Build.Construction.ProjectInSolution, Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", false, false);
                if (s_ProjectInSolution != null)
                {
                    s_ProjectInSolution_ProjectName = s_ProjectInSolution.GetProperty("ProjectName", BindingFlags.NonPublic | BindingFlags.Instance);
                    s_ProjectInSolution_RelativePath = s_ProjectInSolution.GetProperty("RelativePath", BindingFlags.NonPublic | BindingFlags.Instance);
                    s_ProjectInSolution_ProjectGuid = s_ProjectInSolution.GetProperty("ProjectGuid", BindingFlags.NonPublic | BindingFlags.Instance);
                    s_ProjectInSolution_ProjectType = s_ProjectInSolution.GetProperty("ProjectType", BindingFlags.NonPublic | BindingFlags.Instance);
                }
            }
    
            public string ProjectName { get; private set; }
            public string RelativePath { get; private set; }
            public string ProjectGuid { get; private set; }
            public string ProjectType { get; private set; }
    
            public SolutionProject(object solutionProject)
            {
                this.ProjectName = s_ProjectInSolution_ProjectName.GetValue(solutionProject,null) as string;
                this.RelativePath = s_ProjectInSolution_RelativePath.GetValue(solutionProject, null) as string;
                this.ProjectGuid = s_ProjectInSolution_ProjectGuid.GetValue(solutionProject, null) as string;
                this.ProjectType = s_ProjectInSolution_ProjectType.GetValue(solutionProject, null).ToString();
            }
        }
    }

    You could call it using this sample:

    using System;
    using System.Xml;
    
    namespace GetProjectFromSolution
    {
        class Program
        {
            static void Main(string[] args)
            {
                Solution solution = new Solution(@"D:\C#\ConsoleApp12\ConsoleApp12.sln");
                
                foreach(var item in solution.Projects)
                {
                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.Load(@"D:\C#\ConsoleApp12\" + item.RelativePath.ToString());
    
                    try
                    {
                        //.net framework project
                        XmlNamespaceManager mgr = new XmlNamespaceManager(xmldoc.NameTable);
                        mgr.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");
    
                        XmlNode pitem = xmldoc.SelectSingleNode("//x:TargetFrameworkVersion", mgr);
                        if (pitem != null)
                        {
                            string test = pitem.InnerText.ToString();
                            Console.WriteLine(test);
                        }
                        else
                        {
                            //.net core project
                            XmlNode node = xmldoc.DocumentElement.SelectSingleNode("/Project/PropertyGroup/TargetFramework");
                            Console.WriteLine(node.InnerText);
                        }
                    }
                    catch
                    {
                        Console.WriteLine("PLEASE confirm it is right csproj file");
                    }
                }
                Console.ReadLine();
            }
        }
    }

    Any feedback will be expected.

    Best Regards,

    Dylan


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com

    Tuesday, January 7, 2020 4:01 AM