0

we developed an AddIn for Visual Studio 2008 which installs a command bar item in the "Project" context menu (right click on a project in solution explorer). The following, simplified code (in Connect.cs) works fine for all of our machines except one:

object[] contextGUIDS = new object[] { };

string commandName = "My_Command";
string tooltip = "My tooltip";

Command projectCommand = applicationObject.Commands.AddNamedCommand(addInInstance, commandName, commandName, tooltip, false, 1, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled);

CommandBars commandBars = (CommandBars)(fApplicationObject.CommandBars);

CommandBar projectCommandBar = commandBars["Project"];

CommandBarControl projectButton = (CommandBarControl)(projectCommand.AddControl(projectCommandBar, projectCommandBar.Controls.Count + 1));

projectButton.Caption = "My caption";
projectButton.TooltipText = tooltip;

On one single machine, the code will run without an exception, but the button won't show up. Invoking the installation code once more will throw an exception because of an already existing command bar item. However, another item, which should be located in the "Tools" menu is installed and shown properly.

Even though the OS and Visual Studio have been re-installed, the problem still remains (Windows 7 x86 SP1 German, Visual Studio Development Edition SP1 English). We have other machines with the same OS and VS configuration, but the button shows up there properly.

Any hints on this topic are welcome!

Gene
  • 4,192
  • 5
  • 32
  • 56

1 Answers1

1

Because there is more than one command bar named Project in Visual Studio 2008, you need to find the correct one to insert the button into. Luckily, there's an absolutely simple, reasonable and intuitive way to do that.

1. Finding the unique ID of a command bar

Open the registry editor and navigate to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\General. Create a new DWORD value named EnableVSIPLogging and set the value to 1.

That allows you to determine the unique GUID and command ID of the command bar by right clicking the control you want to insert a control into while the SHIFT and CTRL modifiers are pressed. That will bring up a message box like this:

Visual Studio 2008 Debugging Message

Copy the contents of the message by pressing CTRL + C and paste it somewhere into a textbox. Note down the Guid and the CmdID values.

2. Fetching a command bar by Guid and CmdID

You can use the following code snippet to fetch a command bar from the values determined above:

private CommandBar FindCommandBar(Guid guidCmdGroup, uint menuID)
{
  IOleServiceProvider sp = (IOleServiceProvider)fApplicationObject;
  Guid guidSvc = typeof(IVsProfferCommands).GUID;
  Object objService;
  sp.QueryService(ref guidSvc, ref guidSvc, out objService);
  IVsProfferCommands vsProfferCmds = (IVsProfferCommands)objService;
  return vsProfferCmds.FindCommandBar(IntPtr.Zero, ref guidCmdGroup, menuID) as CommandBar;
}

[ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IOleServiceProvider
{

  [PreserveSig]
  int QueryService([In]ref Guid guidService, [In]ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out System.Object obj);

}

Ensure, that the command bars are properly initialized before calling the FindCommandBar method, otherwise the call will fail with a ComException (HResult E_FAIL). Simple way to do this:

private void EnsureInitialized()
{
  var menuBar = ((CommandBars)fApplicationObject.CommandBars)["MenuBar"];
}

Source: http://blogs.msdn.com/b/dr._ex/archive/2007/04/17/using-ivsproffercommands-to-retrieve-a-visual-studio-commandbar.aspx

Gene
  • 4,192
  • 5
  • 32
  • 56