How to find a ProjectItem by the file name
Asked Answered
U

3

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;
}
Unhesitating answered 17/10, 2013 at 12:54 Comment(3)
Unclear: Are you parsing the sln file and then parsing each csproj? Or are you scanning the file system?Restraint
I'm searching in the DTE object which is provided by the VisualStudio.Unhesitating
This seems to work: https://mcmap.net/q/1010975/-get-projectitem-path-without-using-item-document-fullnameRoadbed
R
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..

Resultant answered 17/10, 2013 at 17:17 Comment(5)
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 =(Bennington
I see that this is old, but this really should have the code (or reference) to 'DteHelper.FindItemByName()'.Impertinent
The DteHelper is not a custom code, but Microsoft - built in. This would be a full name: Microsoft.Practices.RecipeFramework.Library.DteHelperMegadeath
Where can I download the Microsoft.Practices.RecipeFramework.Library ? thx in advanceThrottle
@Throttle did you figure out where the library can be found?Lunar
Y
2

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

Yttria answered 26/10, 2020 at 14:55 Comment(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.Grumous
T
0

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

Throttle answered 16/10, 2019 at 18:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.