I'm developing a language service for Visual Studio through a VSPackage. I need to update my parse data whenever files get added/removed from the solution's projects.
I want to subscribe to solution and project events.
I tried as follows, but none of these events get fired when I add/remove projects to the solution or add/remove items to projects.
DTE dte = (DTE)languageService.GetService(typeof(DTE));
if (dte == null)
return;
((Events2)dte.Events).SolutionEvents.ProjectAdded += SolutionEvents_ProjectAdded;
((Events2)dte.Events).SolutionEvents.ProjectRemoved += SolutionEvents_ProjectRemoved;
((Events2)dte.Events).ProjectItemsEvents.ItemAdded += ProjectItemsEvents_ItemAdded;
((Events2)dte.Events).ProjectItemsEvents.ItemRemoved += ProjectItemsEvents_ItemRemoved;
What's the best way to subscribe to these events from a VSPackage? Any help appreciated!
Alternatively you could use IVsSolutionEvents3, which has much better events
Lets focus on
ProjectAdded
event (although described issue is exactly the same for the rest of the events).The code sample you've shown attempts to register the
SolutionEvents_ProjectAdded
handler for theProjectAdded
event. However, theSolutionEvents
object exposing the event, has lifetime scope limited to the closure of its wrapping method (you haven't shown its signature - let's call itConnect
). After the control flow had left that scope, local object has already been garbage collected, so its event is never called:Broken code:
To fix that, you need to assign the
SolutionEvents
object to some variable, whose lifetime spans over theSolutionEvents_ProjectAdded
handler - e.g. over the entire wrapping class. In the example below, the scope extends over the entire type (let's call itConnector
), and ensures that the handler is accessible during the lifetime of that type:Fixed code:
To be more precise, check this MSDN reference - Scoping Variables Appropriately in Event Handlers:
DTE Events are a little weird, you need to cache the event source object (SolutionEvents and ProjectItemEvents in your case), so that COM Interop knows to keep them alive.
More on this @ http://msdn.microsoft.com/en-us/library/ms165650(v=vs.80).aspx