Recently I’ve been working on a Visual Studio 2010 Package to help control some project settings for my team’s development environment. One of the things I needed to be able to access was a list of all the projects.

If like me you thought that DTE2.Solution.Projects would give you that; you’d be wrong.

DTE2.Solution.Projects will only give you the top level list of items under the Solution so any projects nested within Solution Folders are missed. In order to get at these pesky little worms, you need to burrow into the ProjectItem.SubProject property accessed from the ProjectItems collection on the the Project. Just to cap the whole lot off, if you have nested solution folders, then you need some recursion.

okay okay, enough waffle, here’s the code

using System.Collections.Generic;  
using EnvDTE;  
using EnvDTE80;

public static class SolutionProjects  
{
    public static DTE2 GetActiveIDE()
    {
        // Get an instance of currently running Visual Studio IDE.
        DTE2 dte2 = Package.GetGlobalService(typeof(DTE)) as DTE2;
        return dte2;
    }

    public static IList<Project> Projects()
    {
        Projects projects = GetActiveIDE().Solution.Projects;
        List<Project> list = new List<Project>();
        var item = projects.GetEnumerator();
        while (item.MoveNext())
        {
            var project = item.Current as Project;
            if (project == null)
            {
                continue;
            }

            if (project.Kind == ProjectKinds.vsProjectKindSolutionFolder)
            {
                list.AddRange(GetSolutionFolderProjects(project));
            }
            else
            {
                list.Add(project);
            }
        }

        return list;
    }

    private static IEnumerable<Project> GetSolutionFolderProjects(Project solutionFolder)
    {
        List<Project> list = new List<Project>();
        for (var i = 1; i <= solutionFolder.ProjectItems.Count; i++)
        {
            var subProject = solutionFolder.ProjectItems.Item(i).SubProject;
            if (subProject == null)
            {
                continue;
            }

            // If this is another solution folder, do a recursive call, otherwise add
            if (subProject.Kind == ProjectKinds.vsProjectKindSolutionFolder)
            {
               list.AddRange(GetSolutionFolderProjects(subProject));
            }
           else
           {
               list.Add(subProject);
           }
        }
        return list;
    }
}