Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio 2010 Plug-in - Adding a context-menu to the Solution Explorer

I want to add a new option in Visual Studio 2010's solution explorer's context menu for a specific file type. So for example, right clicking on a *.cs file will show the existing context menu plus "my new option".

I'm wondering what the code would look like; and would love a pointer to a good reference for developing visual studio plug-ins. The tutorials/references I'm seeing are conspicuously horrid.

Thanks!

like image 853
Kenn Avatar asked Jun 10 '10 17:06

Kenn


People also ask

How do I add Solution Explorer tab in Visual Studio?

Click on the title bar, and drag it to the right portion of the screen. Eventually you'll see a compas like structure popup. Make sure you hover over the right area and let go of the mouse button. That will bind it to the right side.

How do I use Solution Explorer in Visual Studio code?

You can open any solution, project, folder or file in Visual Studio Code by simply right-clicking it in Solution Explorer and select Open in Visual Studio Code.

How do I dock a solution explorer to the left in Visual Studio?

Just drag and drop onto the mechanic and dock the solution explorer window to the left side of the window.

What is Solution Explorer in Visual Studio?

Solution Explorer is a special window that enables you to manage solutions, projects, and files. It provides a complete view of the files in a project, and it enables you to add or remove files and to organize files into subfolders.


4 Answers

It took me about 5 hours to do this.

There are 2 options, Visual studio Add-in (or shared Add-in) vs Visual studio package.

The package is far more complicated to give you far more control, but for a context menu on the solution explorer it is not needed.

So new project-> Other Project Types -> Extensibility -> Visual Studio Add-in.

Here's a walk-through - Link

Also This one I followed some - Link

I recommend you leave on the option for add to tools menu until you have the context menu working, or to provide a place to put a settings dialog (if you don't write a Tool-> options page.

Here's the connection code:

  _applicationObject = (DTE2)application;
        _addInInstance = (AddIn)addInInst;
        if (connectMode == ext_ConnectMode.ext_cm_UISetup)
        {
            object[] contextGUIDS = new object[] { };
            Commands2 commands = (Commands2)_applicationObject.Commands;
            string toolsMenuName = "Tools";

            //Place the command on the tools menu.
            //Find the MenuBar command bar, which is the top-level command bar holding all the main menu items:
            Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"];

            //Find the Tools command bar on the MenuBar command bar:
            CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName];
            CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl;
            // get popUp command bars where commands will be registered.
            CommandBars cmdBars = (CommandBars)(_applicationObject.CommandBars);
            CommandBar vsBarItem = cmdBars["Item"]; //the pop up for clicking a project Item
            CommandBar vsBarWebItem = cmdBars["Web Item"];
            CommandBar vsBarMultiItem = cmdBars["Cross Project Multi Item"];
            CommandBar vsBarFolder = cmdBars["Folder"];
            CommandBar vsBarWebFolder = cmdBars["Web Folder"];
            CommandBar vsBarProject = cmdBars["Project"]; //the popUpMenu for right clicking a project
            CommandBar vsBarProjectNode = cmdBars["Project Node"];

            //This try/catch block can be duplicated if you wish to add multiple commands to be handled by your Add-in,
            //  just make sure you also update the QueryStatus/Exec method to include the new command names.
            try
            {
                //Add a command to the Commands collection:
                Command command = commands.AddNamedCommand2(_addInInstance, "HintPaths", "HintPaths", "Executes the command for HintPaths", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);

                //Add a control for the command to the tools menu:
                if ((command != null) && (toolsPopup != null))
                {
                    //command.AddControl(toolsPopup.CommandBar, 1);
                    command.AddControl(vsBarProject); 
                }
            }
            catch (System.ArgumentException argEx)
            {
                System.Diagnostics.Debug.Write("Exception in HintPaths:" + argEx.ToString());
                //If we are here, then the exception is probably because a command with that name
                //  already exists. If so there is no need to recreate the command and we can 
                //  safely ignore the exception.
            }
        }
    }

This code checks to see if what the user has selected is a project for instance:

  private Project GetProject()
    {
        if (_applicationObject.Solution == null || _applicationObject.Solution.Projects == null || _applicationObject.Solution.Projects.Count < 1)
            return null;
        if (_applicationObject.SelectedItems.Count == 1 && _applicationObject.SelectedItems.Item(1).Project != null)
            return _applicationObject.SelectedItems.Item(1).Project;
        return null;
    }

Note that certain string names in your code have to match up and I'm not sure which ones they are quite yet as I just did this yesterday.

like image 122
Maslow Avatar answered Oct 08 '22 13:10

Maslow


I found that the best way to go was to make a Visual Studio Package instead of an Visual Studio Add-in. The vsix deployment experience is so slick - the whole thing was a really easy experience. It only supports Visual Studio 2010, but that was good enough in my case.

Here is the resulting vsct:

<Commands package="guidBingfooPluginPkg">
    <Groups>
      <Group guid="guidBingfooPluginCmdSet" id="MyMenuGroup" priority="0x0600">
        <Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_ITEMNODE"/>
      </Group>
    </Groups>

    <Buttons>
      <Button guid="guidBingfooPluginCmdSet" id="cmdidfooLocalBox" priority="0x0100" type="Button">
        <Parent guid="guidBingfooPluginCmdSet" id="MyMenuGroup" />
        <!-- <Icon guid="guidImages" id="bmpPic1" /> -->
        <CommandFlag>DynamicVisibility</CommandFlag>
        <Strings>
          <CommandName>cmdidfooLocalBox</CommandName>
          <ButtonText>View in foo</ButtonText>
        </Strings>
      </Button>

      <Button guid="guidBingfooPluginCmdSet" id="cmdidfooTestBed" priority="0x0100" type="Button">
        <Parent guid="guidBingfooPluginCmdSet" id="MyMenuGroup" />
        <CommandFlag>DynamicVisibility</CommandFlag>
        <Strings>
          <CommandName>cmdidfooTestBed</CommandName>
          <ButtonText>View in foo on Test Beds</ButtonText>
        </Strings>
      </Button>

    </Buttons>

    <Bitmaps>
      <Bitmap guid="guidImages" href="Resources\Images_32bit.bmp" usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows"/>
    </Bitmaps>
  </Commands>

  <Symbols>
    <GuidSymbol name="guidBingfooPluginPkg" value="{62c4a13c-cc61-44a0-9e47-33111bd323ce}" />

    <GuidSymbol name="guidBingfooPluginCmdSet" value="{59166210-d88c-4259-9809-418bc332b0ab}">
      <IDSymbol name="MyMenuGroup" value="0x1020" />
      <IDSymbol name="cmdidfooLocalBox" value="0x0100" />
      <IDSymbol name="cmdidfooTestBed" value="0x0101" />
    </GuidSymbol>

    <GuidSymbol name="guidImages" value="{2dff8307-a49a-4951-a236-82e047385960}" >
      <IDSymbol name="bmpPic1" value="1" />
      <IDSymbol name="bmpPic2" value="2" />
      <IDSymbol name="bmpPicSearch" value="3" />
      <IDSymbol name="bmpPicX" value="4" />
      <IDSymbol name="bmpPicArrows" value="5" />
    </GuidSymbol>
  </Symbols>
</CommandTable>
like image 33
Kenn Avatar answered Oct 08 '22 12:10

Kenn


UPDATE:

GAX/GAT for VS2010 also available from http://msdn.microsoft.com/en-us/library/ff687173

ORIGINAL POST

Well is horrid because VS is really complex. Using GAX/GAT was possible, but there's no VS2010 Version yet. What I suggest is downloading some samples from the Visual Studio Gallery to try to understand how the whole thing works, sadly not an easy task.

HTH

like image 30
Marcote Avatar answered Oct 08 '22 11:10

Marcote


I found myself having to add an item to the code editor window context menu, which ended up being cmdBars["Script Context"] as I was wanting it specifically for JavaScript files.

As a technique for finding this which I felt useful sharing, I added the new menu item to all (456) menu controls in visual studio with the following loop:

foreach (CommandBar cc in cmdBars)
{
    if (cc.Index >= 1 && cc.Index <= 456)
    {
        command.AddControl(cmdBars[cc.NameLocal]);
    }
}

I then narrowed this using a divide and conquer technique by adjusting the bounds of the loop:

    if (cc.Index >= 1 && cc.Index <= 256)
    ...
    if (cc.Index >= 1 && cc.Index <= 128)
    ...
    if (cc.Index >= 64 && cc.Index <= 128)
    ...etc...

Until I eventually found what I was looking for.

(The related question for this is at Visual Studio 2010 Plug-in - Adding a context-menu to the Editor Window)

like image 32
James Wiseman Avatar answered Oct 08 '22 11:10

James Wiseman