Selected project from Solution Explorer
Asked Answered
A

1

6

I am writing a customization package for Visual Studio 2010 (vsix).

What I need to do is to add a context menu button to the Project nodes in Solution Explorer.

I've managed to get the context menu to appear when right-clicking the Project nodes, but my next challenge is to get a reference to the Project object that's been clicked. Currently I am able to get the project by going through the active document in the IDE using the code below.

DTE dte = (DTE)ServiceProvider.GlobalProvider.GetService(typeof(DTE));
Project project = dte.ActiveDocument.ProjectItem.ContainingProject;

So my question is: how do I get a similar reference to the project selected in the solution explorer?

Adrien answered 15/6, 2012 at 11:23 Comment(0)
A
12

I figured it out. Might as well share the info.

By using the SVsShellMonitorSelection service I can get a reference to the selected hierarchy as a IVsHierarchy, which in turn allows me to get a reference to the selected object. This may then be cast to classes such as Project, ProjectItem, etc, based on what is selected in the Solution Explorer. Handy!

IntPtr hierarchyPointer, selectionContainerPointer;
Object selectedObject  = null;
IVsMultiItemSelect multiItemSelect;
uint projectItemId;

IVsMonitorSelection monitorSelection = 
        (IVsMonitorSelection)Package.GetGlobalService(
        typeof(SVsShellMonitorSelection));

monitorSelection.GetCurrentSelection(out hierarchyPointer, 
                                     out projectItemId, 
                                     out multiItemSelect, 
                                     out selectionContainerPointer);

IVsHierarchy selectedHierarchy = Marshal.GetTypedObjectForIUnknown(
                                     hierarchyPointer, 
                                     typeof(IVsHierarchy)) as IVsHierarchy;

if (selectedHierarchy != null)
{
    ErrorHandler.ThrowOnFailure(selectedHierarchy.GetProperty(
                                      projectItemId,
                                      (int)__VSHPROPID.VSHPROPID_ExtObject, 
                                      out selectedObject));
}

Project selectedProject = selectedObject as Project;

Here's the source

Adrien answered 16/6, 2012 at 6:46 Comment(4)
I'm so happy I found this, couldn't find out anywhere else how to do this. :DKolb
I think you are missing Marshal.Release(hierarchyPtr); Marshal.Release(selectionContainerPointer); at the end so as to avoid a memory leak. Otherwise great!Lancey
This might be obvious but as a novice user of IntPtr it is worth pointing out that you can check selectionContainerPointer == IntPtr.Zero before calling Marshal.Release on it to avoid a null pointer exception.Blocking
Thank you so much for this. It's been 12 years since you wrote this and I still haven't managed to find how to do this anywhere else. Am I really bad at looking for answers or is this just very poorly documented?Skirr

© 2022 - 2024 — McMap. All rights reserved.