Search code examples
c#.netvisual-studioenvdte

How to find a ProjectItem by the file name


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;
}

Solution

  • 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..