Why does my Outlook event seem to stop working

Wes has a good post over on his blog explaining another common problem that a lot of Outlook solution developers run into:

Imagine we have some code in an Outlook addin that looks similar to code below. Does anyone see anything wrong with it? It simply places a button on the menu bar and shows a message box when the button is clicked. The code works for sometime but then all of a sudden the button mysteriously stops working. What gives?  

 using Office = Microsoft.Office.Core;
using Outlook = Microsoft.Office.Interop.Outlook;
...
 void SetupCommandBar(Outlook.Application application)
{
    Office.CommandBar menu = 
       application.ActiveExplorer().CommandBars.ActiveMenuBar;

    Office.CommandBarButton button = menu.Controls.Add(
        Office.MsoControlType.msoControlButton,
        Type.Missing, Type.Missing, Type.Missing, true) 
        as Office.CommandBarButton;

    button.Caption = "Click Me!";
    button.Click += 
      new Office._CommandBarButtonEvents_ClickEventHandler(button_Click);
}
 void button_Click(Microsoft.Office.Core.CommandBarButton Ctrl,
ref bool CancelDefault)
{
    System.Windows.Forms.MessageBox.Show("Clicked Button!");
}

The button stops working due to the mystical powers of the .Net garbage collector. If we look closely we notice that the button object is locally scoped in the SetupCommandBar function, thus once we execute that function the button object is free to be cleaned up. However, until the button object is actually destroyed by the garbage collector the button click event will fire and the button will work. Due to the non-deterministic nature of the garbage collector we have no idea how long the button will work. In my simple testing it seemed to work for a little while but if you want to speed up the process add a call go GC.Collect in the button_Click callback.

The easiest fix for this problem is to change the scope of the button object to be a member variable of enclosing class. By doing this we ensure that the button object stays alive and works until we are ready for it to stop working.