Delen via


Visual Studio 2012 and BuildEvents in addins

While testing the functionalities of the new Visual Studio 2012, I came across a scenario that seemed a little ambiguous and, at first glance, pointed to a bug.

Let’s say that you create an add-in in VS 2010 and you need to have it perform different actions on the build events.
You will add the

_applicationObject.Events.BuildEvents.OnBuildBegin += new _dispBuildEvents_OnBuildBeginEventHandler(BuildEvents_OnBuildBegin);

instruction in the OnConnection() method and then add the BuildEvents_OnBuildBegin method:

  void BuildEvents_OnBuildBegin(vsBuildScope Scope, vsBuildAction Action)
        {
              Console.WriteLine("onbuildbegin");
        }

Build the add-in, go to Debug->Start Debugging, which will open a new instance of VS 2010. Create a new application which will use the add-in, load the add-in with Add-in Manager and put a breakpoint in the BuildEvents_OnBuildBegin method. Build the new application and you will see the execution stopping at the breakpoint, as expected.

If you do the same scenario in VS 2012, you can see that the OnBuildBegin event seems not to be raised anymore and the BuildEvents_OnBuildBegin method is no longer being called.
The apparent ‘workaround’ for this is to add a reference to _applicationObject.Events.BuildEvents in the OnConnection method of the add-in Connect class: 

private _BuildEvents _buildEvents;
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
              {
            _buildEvents = _applicationObject.Events.BuildEvents;

Curious to see if this is a bug in VS 2012, I looked for previous scenarios and bugs referring to this issue. I could find a reference to a similar situation in VS 2003, which was signaled as a bug and seemingly fixed. I also found this KB, which explains pretty much the same thing and offers the same solution:https://support.microsoft.com/kb/555102

It all pointed towards a bug which existed in earlier versions, had been fixed and the fix wasn’t ported to VS 2012. It turned out that this wasn’t the case.

When the developers of VS 2012 analyzed the call stack, it could be seen that the RCW for the BuildEvents object was finalized by the GC and the event is unadvised. Adding a reference to BuildEvents in the class saves the object from being GC-ed and is actually the correct way to do it. The reasons why this used to work on previous versions are not quite clear, but it has probably something to do with a very short cycle for subscribe and receive event, in which the GC didn’t intervene and the event could be caught before finalizing the object.

Also, this wasn’t always true, as we can see if we dig deeper and find these articles and discussions which mention the problem for VS 2005, VS 2008 and VS 2010:
https://www.mztools.com/articles/2005/MZ2005012.aspx
https://social.msdn.microsoft.com/Forums/en/vsx/thread/d48448d1-b00e-4520-bdf7-685640b0f072
https://social.msdn.microsoft.com/Forums/en/vsx/thread/ee827d4f-db11-497b-9135-bb344a144d52