2010-10-06 79 views
11

我在包內部做了一個擴展,並且調用以下代碼(當用戶按下工具欄中的按鈕時發生):DTE事件的訂閱似乎不起作用 - 事件不會被調用

DocumentEvents documentEvents = (DTE2)GetService(typeof(DTE)); 
_dte.Events.DebuggerEvents.OnEnterBreakMode += DebuggerEvents_OnEnterBreakMode; 
_dte.Events.DebuggerEvents.OnEnterDesignMode += DebuggerEvents_OnEnterDesignMode; 
_dte.Events.DebuggerEvents.OnContextChanged += DebuggerEvents_OnContextChanged; 
_dte.Events.DocumentEvents.DocumentSaved += new _dispDocumentEvents_DocumentSavedEventHandler(DocumentEvents_DocumentSaved); 
_dte.Events.DocumentEvents.DocumentOpened += new _dispDocumentEvents_DocumentOpenedEventHandler(DocumentEvents_DocumentOpened); 
void DocumentEvents_DocumentOpened(Document Document) 
{ 
} 

void DocumentEvents_DocumentSaved(Document Document) 
{ 
} 

void DebuggerEvents_OnEnterBreakMode(dbgEventReason Reason, ref dbgExecutionAction ExecutionAction) 
{ 
} 

void DebuggerEvents_OnContextChanged(Process NewProcess, Program NewProgram, Thread NewThread, StackFrame NewStackFrame) 
{ 
} 

private void DebuggerEvents_OnEnterDesignMode(dbgEventReason reason) 
{ 
} 

第一個也是主要的問題是訂閱該事件不起作用。我已經試過:

  • 打開新文件
  • 從調試(因而理應觸發OnEnterDesignMode
  • 拆卸保存文檔

這些都不似乎有任何影響,回調函數是從未打過電話

第二個問題是對事件行的訂閱工作USUALLY(訂閱本身,回調不起作用,如上所述)但經過一段時間運行訂閱行,e.g:

_dte.Events.DebuggerEvents.OnEnterBreakMode -= DebuggerEvents_OnEnterBreakMode; 

導致異常:

Exception occured! 
System.Runtime.InteropServices.InvalidComObjectException: COM object that has been separated from its underlying RCW cannot be used. 
    at System.StubHelpers.StubHelpers.StubRegisterRCW(Object pThis, IntPtr pThread) 
    at System.Runtime.InteropServices.UCOMIConnectionPoint.Unadvise(Int32 dwCookie) 
    at EnvDTE._dispDebuggerEvents_EventProvider.remove_OnEnterDesignMode(_dispDebuggerEvents_OnEnterDesignModeEventHandler A_1) 

任何想法將受到歡迎

謝謝! 維塔利

回答

13

過帳answer,我從MSDN論壇得到的,由Ryan莫爾登,在情況下,它可以幫助任何人:

我相信這裏的問題是 CLR如何處理COM端點(事件 匯) 。如果我沒有記錯,當 你打 _applicationObject.Events.DebuggerEvents你的「鏈」 CLR將 創建一個新的對象DebuggerEvents爲 屬性訪問的 一部分,將不緩存 它,它爲此回來給你,你 註冊一個事件處理它(這 創建 臨時對象和你的對象由於 的代表之間有很強的參考,但不能從您的 對象到臨時對象,這 將防止GC)。那麼你不要 存儲該對象的任何地方,因此它是 立即GC合格,並將最終被GC'ed 。

我改變了代碼來存儲DebuggerEvents作爲一個字段,它都開始正常工作。

+0

我有同樣的問題,這個解決它。謝謝! – 2011-05-04 16:44:58

+0

您節省了2天的工作時間。在我的包裏面:'private static SolutionEvents solutionEvents; protected override void Initialize() { ApplicationObject = GetService(typeof(DTE))as DTE2; solutionEvents = ApplicationObject.Events.SolutionEvents;}' – LukTar 2017-10-19 12:14:31

8

這裏是@VitalyB意味着使用代碼:

// list where we will place events. 
// make sure that this variable is on global scope so that GC does not delete the evvents 
List<object> events = new List<object>(); 

public void AddEvents(EnvDTE dte) 
{ 
    // create an event when a document is open 
    var docEvent = dte.Events.DocumentEvents; 

    // add event to list so that GC does not remove it 
    events.Add(docEvent); 

    docEvent.DocumentOpened += (document)=>{ 

     Console.Write("document was opened!"); 
    }; 

    // you may add more events: 
    var commandEvent = dte.Events.CommandEvents; 
    events.Add(commandEvent); 

    commandEvent.AfterExecute+= etc... 

}