views:

416

answers:

3

I'm using this code to add an item to the code window right click menu:

public void OnConnection(
 object application, 
 ext_ConnectMode connectMode, 
 object addInInst, 
 ref Array custom)
{
    _applicationObject = (DTE2)application;
    _addInInstance = (AddIn)addInInst;

    object[] contextGUIDS = new object[] { };
    Command codeWindowCommand = null;
    CommandBarControl codeWindowButton;
    CommandBar codeCommandBar;
    CommandBars commandBars;

    try
    {
        codeWindowCommand = _applicationObject.Commands.Item(
            _addInInstance.ProgID + "." + CODEWINDOW_COMMAND_NAME, 0);
    }
    catch
    {
    }

    if (codeWindowCommand == null)
    {
        codeWindowCommand = _applicationObject.Commands.AddNamedCommand(
            _addInInstance, 
            CODEWINDOW_COMMAND_NAME, 
            CODEWINDOW_COMMAND_NAME, 
            "Pastebin selected code", 
            true, 
            18, 
            ref contextGUIDS, 
            (int)vsCommandStatus.vsCommandStatusSupported + 
            (int)vsCommandStatus.vsCommandStatusEnabled);
    }

    commandBars = (CommandBars)_applicationObject.CommandBars;

    codeCommandBar = commandBars["Code Window"];

    codeWindowButton = (CommandBarControl)codeWindowCommand.AddControl(
        codeCommandBar, codeCommandBar.Controls.Count + 1);
    codeWindowButton.Caption = "Text for button";
    codeWindowButton.TooltipText = "Tooltip for button";
}

and the addin is set to autostart. However each time the run VS2008 it adds another button to the menu until I totally delete the addin. Anyone know how I fix this?

I would for example wrap the Command.AddControl() and later stuff in an if that only executes if the button doesn't already exist, but I can't seem to find a way to check this in the API?

+1  A: 

I remember seeing this problem elsewhere, and the reason was that the OnConnection method can be called at multiple times for multiple reasons (with different values of connectMode), so there is some trickery (or peculiarities, depending on how you look at it and how much of this you know) involved.

However, I am not an expert on this topic, so here are some links that will help you:

HOWTO: Use correctly the OnConnection method of a Visual Studio add-in

HOWTO: Adding buttons, commandbars and toolbars to Visual Studio .NET from an add-in

HOWTO: Controlling the state of command in a Visual Studio add-in

Those are somewhat too long to just summarize here (at least it seems like that to me), but they do have the information you need.

Also, here is a list of articles on writing VS addins, which will probably be very helpful: http://www.mztools.com/resources_vsnet_addins.aspx

HTH.


EDIT: Money J's answer is a bit more to the point, I suppose, and is basically a very short summary of what you need to do, and if that's all you're after - great. However, I believe that the information contained on the pages I provided the links to is very useful, so you might want to read that as well.

AASoft
I'll prolly do a short term fix and then delve into that info when I get the time. Most of what I could find always dealt with doing it in that horrible language known as vb.net which wasn't too useful so thanks.
ewanm89
I'll check it works tomorrow, or Monday when I have time, moving tomorrow so. Lots of packing to do.
ewanm89
Thanks, those links were a big help along with this one: http://www.mztools.com/articles/2006/MZ2006014.aspx
ewanm89
A: 

I haven't written an addin for VS.NET 2008 before, but seeing what you have available on your method:

Check for ext_cm_UISetup?

 if(connectMode == ext_ConnectMode.ext_cm_UISetup)
    {

also, in your try block you should be able to use the resourcemanager...

 ResourceManager resourceManager = new     
          ResourceManager("MyAddin1.CommandBar",  
          Assembly.GetExecutingAssembly());
        CultureInfo cultureInfo = new 
          System.Globalization.CultureInfo
          (_applicationObject.LocaleID);
        string resourceName = String.Concat(cultureInfo.
          TwoLetterISOLanguageName, "Tools");
        toolsMenuName = resourceManager.GetString(resourceName);

And a handy diagram that might help in the future.

http://msdn.microsoft.com/en-us/library/za2b25t3.aspx

I tried that connectMode stuff in all the ways suggested here and they all end up meaning I get no menu item at all...
ewanm89
I'm still trying to see what the ResourceManager code is even trying to do, and how it relates to my variable names.
ewanm89
A: 

Try changing:

codeWindowCommand = _applicationObject.Commands.Item(_addInInstance.ProgID + "." + CODEWINDOW_COMMAND_NAME, 0);

...to:

codeWindowCommand = _applicationObject.Commands.Item(_addInInstance.ProgID + "." + CODEWINDOW_COMMAND_NAME, -1);

...and wrap the whole thing in:

#if DEBUG
if (connectMode == ext_ConnectMode.ext_cm_UISetup)
#else
if (connectMode == ext_ConnectMode.ext_cm_Startup || connectMode == ext_ConnectMode.ext_cm_AfterStartup)
#endif
{
    //add-in startup code goes here
}
KristoferA - Huagati.com
I already tried the -1 as it says it's optional.
ewanm89
Ok, and did you add the connectMode check at the same time? OnConnection can be called multiple times in different contexts and also behaves differently depending on LoadBehaviour/CommandPreload settings in the .addin file...
KristoferA - Huagati.com
I tried that connectMode stuff in all the ways suggested here and they all end up meaning I get no menu item at all...The load behaviour is to start on VS2008 startup.
ewanm89