我在包中做了一个扩展,我调用了以下代码(当用户按下工具栏中的按钮时发生):
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)
{
}
第一个和主要问题是订阅该事件不起作用。我试过了:
这些似乎都没有任何效果,并且从未调用回调函数。
第二个问题是对事件行的订阅是USUALLY(订阅本身,回调不能如上所述),但是在运行订阅行后一段时间,例如:
_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)
欢迎任何想法
谢谢! 维塔利彼得
答案 0 :(得分:14)
发布我从MSDN论坛获得的answer,由Ryan Molden提供,以防万一:
我相信这里的问题是怎么回事 CLR处理COM端点(事件 汇)。如果我没记错的话 你打了 _applicationObject.Events.DebuggerEvents CLR将成为你'链'的一部分 为。创建一个新的DebuggerEvents对象 属性访问并且不会缓存 它,那么它回到你身边,你 为它注册一个事件处理程序(其中 在...之间产生强烈的反对 TEMPORARY对象和你的对象到期 给代表,但不是来自你的代表 对象到临时对象,哪个 会阻止GC)。那你没有 将该对象存储在任何地方 立即GC符合条件且将会 最终是GC'ed。
我更改了代码以将DebuggerEvents存储为字段,这一切都开始正常工作。
答案 1 :(得分: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...
}