0

I'm writing a Visual Studio extension and I want to iterate over all files in the current solution (to find files with the same name ignoring extensions). After looking around I found out I can iterate over all projects in the solution and from there recursively over all Project items and their child items.

In a small C# example solution this works nicely, but if I try this on a bigger C++ solution from work it doesn't. In this solution all projects are sorted in solution folders. Solution.Projects contains said folders and each folder's ProjectItems property contains the projects (vcxproj files). BUT all these project's ProjectItems properties are null. Not empty, null. So the recursion ends rather fast and doesn't see a single actual document.

What the heck? What can I do about this? How can I get the documents here?

I already looked at these two. The accepted answers there are what I already have :/

Enumerate all files in current visual studio project

Get a list of Solution/Project Files for VS Add-in or DXCore Plugin

My Code starting the recursion

DTE2 dte2 = Package.GetGlobalService(typeof(DTE)) as DTE2;
foreach (Project project in dte2.Solution.Projects)
{
    OpenAll(project.ProjectItems);
}

recursive function

protected void OpenAll(ProjectItems _aItems)
{
    Dispatcher.VerifyAccess();
    foreach (ProjectItem item in _aItems)
    {
        if (item.Name != null)
        {
            string name = item.Name.Contains(".") ? item.Name.Substring(0, item.Name.IndexOf('.')) : item.Name;
            if (string.Compare(StrName, name, true) == 0 && !item.IsOpen)
            {
                // if it's an item with the right name open it
                item.Open();
            }
        }
        if (item.ProjectItems != null && item.ProjectItems.Count > 0)
        {
            // Process sub items
            // I NEVER GET HERE BECAUSE ProjectItems IS NULL!
            OpenAll(item.ProjectItems);
        }
    }
}

1 Answers1

0

I found the problem. Folders and files are represented as SolutionItems, but projects within SulutionItems are not SolutionItems but Projects, kept in the SubProject property. Therefore to do a complete traversal of the solution you need something like this:

// Start the recursion
DTE2 dte2 = Package.GetGlobalService(typeof(DTE)) as DTE2;
foreach (Project project in dte2.Solution.Projects)
{
    OpenSimilarDocuments(project);
}

Recursive functions

private void OpenSimilarDocuments(Project _project)
{
    Dispatcher.VerifyAccess();
    if (_project == null)
    {
        return;
    }
    // Traverse all ProjectItems of the project
    if (_project.ProjectItems != null)
    {
        foreach (ProjectItem item in _project.ProjectItems)
        {
            OpenSimilarDocuments(item);
        }
    }
}

private void OpenSimilarDocuments(ProjectItem _item)
{
    Dispatcher.VerifyAccess();
    if (_item == null)
    {
        return;
    }
    // See if it is a file we want to open
    if (_item.Name != null)
    {
        string name = _item.Name.Contains(".") ? _item.Name.Substring(0, _item.Name.IndexOf('.')) : _item.Name;
        if (string.Compare(StrName, name, true) == 0 && !_item.IsOpen)
        {
            _item.Open();
        }
    }
    // Traverse all child ProjectItems
    if (_item.ProjectItems != null)
    {
        foreach (ProjectItem item in _item.ProjectItems)
        {
            OpenSimilarDocuments(item);
        }
    }
    // See if we have a child project and traverse that as well
    if (_item.SubProject != null)
    {
        OpenSimilarDocuments(_item.SubProject);
    }
}

What still puzzles me is that to see if a ProjectItem is itself or contains a document you cant simply use ProjectItem.Document != null since some ProjectItems don't even have this field and therefore the code will crash, but that's something else... <.<