none
Some DTE events fire but others don't?

    Question

  • As discussed in this article http://www.mztools.com/articles/2005/MZ2005012.aspx, I am aware that I need to store local references to each DTE event type in order to prevent them from going out of scope.  This method works fine when I attach BuildEvents and DocumentEvents, but I'm not getting any DebuggerEvents to fire.  Based on my reading of another article (http://www.mztools.com/articles/2007/mz2007020.aspx) it would appear that the DebuggerEvents event "OnEnterRunMode" gets fired whenever the user attempts to run the current project.  However, my handler method isn't getting called.  Am I missing some additional step or should I be looking at a different event somewhere else in the DTE?

     

    And here's my code:

     

    private BuildEvents buildEvents = null;
    private DocumentEvents documentEvents = null;
    private DebuggerEvents debuggerEvents = null;
    
    ...
    
    buildEvents = dte.Events.BuildEvents;
    documentEvents = dte.Events.DocumentEvents;
    debuggerEvents = dte.Events.DebuggerEvents;
            
    //attach to various build events
    buildEvents.OnBuildDone += new _dispBuildEvents_OnBuildDoneEventHandler(OnBuildDone);
    
    //attach to document events
    documentEvents.DocumentSaved += new _dispDocumentEvents_DocumentSavedEventHandler(DocumentSaved);
    
    //attach to debug events
    debuggerEvents.OnEnterRunMode += new _dispDebuggerEvents_OnEnterRunModeEventHandler(debuggerEvents_OnEnterRunMode);
    
    ...
    
    void debuggerEvents_OnEnterRunMode(dbgEventReason Reason)
    {
            Trace.WriteLine("run mode");
    }
    
    


     


    • Edited by adamcarter Tuesday, November 29, 2011 11:03 PM
    Tuesday, November 29, 2011 11:02 PM

Answers

  • 3 was more a statement of left out information, which can make debugging through forum posts much harder :)

    1:  You said it worked if you sign up inside your Initialize method, but not if you sign up within another class?  I assume in that case you were creating said 'other class' inside your Initialize method and passing it the DTE object at that time?  If not were you calling some method on that class from inside your Initialize method to pass it the DTE object?

    2:  Is your package loaded?  This sounds silly, but, the only time your Initialize method would be called is when your package is loaded, by default your package is not loaded at startup so you couldn't sign up for any events or get any callbacks before you were loaded.

    3:  No, if you have a non-null DebuggerEvents I would expect it to work and not suddenly become null.  I was pointing out if it was null (i.e. if the line dteRef.Events.DebuggerEvents returned null then the next line, that syncs OnEnterRunMode would hit a null ref) exceptions would be swallowed on COM boundaries, so you wouldn't see VS break necessarily in such cases unless you have set it up to do so while debugging.

    At this point, since Ed has said it works for him and you have confirmed it works if done inside your Initialize method and the only unknown is this 'other class' a complete repro including the package class and the other class would be needed to try to understand what is going on.  There should be no reason an event listener in another class isn't being called assuming all the references are strongly rooted.

    Ryan

    • Marked as answer by adamcarter Thursday, December 01, 2011 9:46 PM
    Wednesday, November 30, 2011 11:39 PM
    Moderator

All replies

  • Hi Adam,

    It works for me. This event should fire when you launch the project under the debugger (F5). Are you running the project or are you "debugging" the project. If you're just running the project, the debugger isn't involved, so the event will not be fired.

    Sincerely,


    Ed Dore
    Wednesday, November 30, 2011 5:53 AM
    Moderator
  • Ed,

    After further investigation, I can catch the event when I attach to it inside my package's Initialize() function, but not inside a separate class.  Example:

            protected override void Initialize()
            {
                base.Initialize();
    
                //dteRef is an instance variable
                dteRef = (DTE2)OSBIDEPackage.GetGlobalService(typeof(SDTE));
    
                //same goes with debuggerEvents
                debuggerEvents = dteRef.Events.DebuggerEvents;
    
                //this works
                debuggerEvents.OnEnterRunMode += new _dispDebuggerEvents_OnEnterRunModeEventHandler(debuggerEvents_OnEnterRunMode);
    
                //passing the DTE into a separate class and attempting to listen to the same event doesn't work
                logger = new EventLogger(dteRef);
            }
    


     Am I running into some sort of restriction?  

     

    Thanks,

    --Adam

    Wednesday, November 30, 2011 8:52 PM
  • Services fetched through a package's service provider generally are not available before Intiailize (SetSite).  You can get DTE anytime (mostly) via ServiceProvider.GlobalProvider, but from your initial code you left out:

    1)  Where you are getting the DTE reference.

    2)  Where you are getting the service provider that yields the DTE reference.

    3)  That the original code was 'in another class'

    4)  The lifetime control/creation pattern of said 'other class'.

    5)  Whether the original code was throwing exceptions that are being swallowed (i.e. if GetService returned null for DTE and you call DTE.Event, boom, null ref, likely swallowed by a COM boundary).  I assume this wasn't the case as you were getting 'some events', but perhaps DebuggerEvents was null (guessing as with a complete repro it is all we can really do).

    Ryan


    Wednesday, November 30, 2011 9:49 PM
    Moderator
  • I'm quite new to package development so I'm not quite sure that I understand your questions, but here I go:

    1. I'm pulling the DTE reference from within the Initialize() method inside the Package class auto generated for me by the Visual Studio Package creation wizard.

    2. I'm assuming that my package is the service provider?

    3. I don't think that this one is a question, per se.

    4. The other class is an instance variable of the Package mentioned in question #1

    5.  I've stepped through the debugger and it looks like my local DebuggerEvents reference isn't null.  Even so, what would cause the DebuggerEvents to be null on one line but not null on the line that directly precedes it? 

    --Adam

    Wednesday, November 30, 2011 10:39 PM
  • 3 was more a statement of left out information, which can make debugging through forum posts much harder :)

    1:  You said it worked if you sign up inside your Initialize method, but not if you sign up within another class?  I assume in that case you were creating said 'other class' inside your Initialize method and passing it the DTE object at that time?  If not were you calling some method on that class from inside your Initialize method to pass it the DTE object?

    2:  Is your package loaded?  This sounds silly, but, the only time your Initialize method would be called is when your package is loaded, by default your package is not loaded at startup so you couldn't sign up for any events or get any callbacks before you were loaded.

    3:  No, if you have a non-null DebuggerEvents I would expect it to work and not suddenly become null.  I was pointing out if it was null (i.e. if the line dteRef.Events.DebuggerEvents returned null then the next line, that syncs OnEnterRunMode would hit a null ref) exceptions would be swallowed on COM boundaries, so you wouldn't see VS break necessarily in such cases unless you have set it up to do so while debugging.

    At this point, since Ed has said it works for him and you have confirmed it works if done inside your Initialize method and the only unknown is this 'other class' a complete repro including the package class and the other class would be needed to try to understand what is going on.  There should be no reason an event listener in another class isn't being called assuming all the references are strongly rooted.

    Ryan

    • Marked as answer by adamcarter Thursday, December 01, 2011 9:46 PM
    Wednesday, November 30, 2011 11:39 PM
    Moderator
  • Ryan,

    I appreciate your continued responses.  With regards to your questions, I'm instantiating my instance variable within the Initialize() method and passing the DTE reference through the class' constructor.  I'm pretty sure that my package is loaded, I'm decorating my Package with the "[ProvideAutoLoad(UIContextGuids80.SolutionExists)]" attribute.  

     

    From a design perspective, I'm fine with keeping my listeners inside my package.  This was more of a, "Why doesn't this work" curiosity than an impediment.  

    Thanks,

    --Adam

    Thursday, December 01, 2011 9:46 PM