12

I'm developing a custom tool for the Visual Studio. The tool is assigned to the file, at the time when the file changed I receive name of this file and should generate some changes in the project. I need to find a ProjectItem by the received file name. I have found only one solution it's enumerate all project items in the each project of the solution. But it seems to be huge solution. Is there a way to get a project item by the file name without enumeration?

This is my implementation of the Generate method of the IVsSingleFileGenerator

public int Generate(string sourceFilePath, string sourceFileContent, string defaultNamespace, IntPtr[] outputFileContents, out uint output, IVsGeneratorProgress generateProgress)
{
    var dte = (EnvDTE.DTE)Package.GetGlobalService(typeof(EnvDTE.DTE));

    ProjectItem projectItem = null;

    foreach (Project project in dte.Solution.Projects)
    {
        foreach (ProjectItem item in project.ProjectItems)
        {
            var path = item.Properties.Item("FullPath").Value;
            if (sourceFilePath.Equals(path, StringComparison.OrdinalIgnoreCase))
            {
                projectItem = item;
            }
        }               
    }

    output = 0;
    outputFileContents[0] = IntPtr.Zero;

    return Microsoft.VisualStudio.VSConstants.S_OK;
}
Viacheslav Smityukh
  • 5,652
  • 4
  • 24
  • 42

3 Answers3

8

I am using this user-friendly world of DTE as well, to create a Guidance. I did not find any better solution. Basically these are methods I am using:

Iterate projects:

public static ProjectItem FindSolutionItemByName(DTE dte, string name, bool recursive)
{
    ProjectItem projectItem = null;
    foreach (Project project in dte.Solution.Projects)
    {
        projectItem = FindProjectItemInProject(project, name, recursive);

        if (projectItem != null)
        {
            break;
        }
    }
    return projectItem;
}

Find in a single project:

public static ProjectItem FindProjectItemInProject(Project project, string name, bool recursive)
{
    ProjectItem projectItem = null;

    if (project.Kind != Constants.vsProjectKindSolutionItems)
    {
        if (project.ProjectItems != null && project.ProjectItems.Count > 0)
        {
            projectItem = DteHelper.FindItemByName(project.ProjectItems, name, recursive);
        }
    }
    else
    {
        // if solution folder, one of its ProjectItems might be a real project
        foreach (ProjectItem item in project.ProjectItems)
        {
            Project realProject = item.Object as Project;

            if (realProject != null)
            {
                projectItem = FindProjectItemInProject(realProject, name, recursive);

                if (projectItem != null)
                {
                    break;
                }
            }
        }
    }

    return projectItem;
}

The code I am using with more snippets could be found here, as a Guidance for new projects. Search for and take the source code..

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • 2
    as a warning this doesn't account at all for solution folders. `dteSolution.Projects` returns top level items only, not projects that are in solution folders =( – Maslow Jun 13 '14 at 17:10
  • 4
    I see that this is old, but this really should have the code (or reference) to 'DteHelper.FindItemByName()'. – Steve Kinyon Sep 11 '15 at 17:08
  • 4
    The **DteHelper** is not a custom code, but Microsoft - built in. This would be a full name: **`Microsoft.Practices.RecipeFramework.Library.DteHelper`** – Radim Köhler Jan 05 '16 at 09:45
  • Where can I download the Microsoft.Practices.RecipeFramework.Library ? thx in advance – Jon Dec 05 '18 at 13:27
  • @Jon did you figure out where the library can be found? – Twenty Oct 16 '19 at 14:35
2

May be a little late but use DTE2.Solution.FindProjectItem(fullPathofChangedFile);

Eugene
  • 101
  • 1
  • 3
  • 1
    `FindProjectItem(string FileName)` is a member of `EnvDTE._Solution` in `EnvDTE.dll, 8.0.0.0` (i.e. Visual Studio 2005), btw - so you don't need `DTE2`, just `DTE` is fine. – Dai Apr 05 '21 at 06:53
0

To get project.documents - find an item - use Linq to query files

Jon
  • 1,608
  • 7
  • 25
  • 38