Vit*_*lyB 12 vsx visual-studio-2010 visual-studio
我在包中做了一个扩展,我调用了下面的代码(当用户按下工具栏中的按钮时发生):
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)
{
}
Run Code Online (Sandbox Code Playgroud)
第一个和主要问题是订阅该事件不起作用.我试过了:
这些似乎都没有任何效果,并且从不调用回调函数.
第二个问题是对事件行的订阅是USUALLY(订阅本身,回调不能像上面描述的那样工作)但是在运行订阅行一段时间之后,例如:
_dte.Events.DebuggerEvents.OnEnterBreakMode -= DebuggerEvents_OnEnterBreakMode;
Run Code Online (Sandbox Code Playgroud)
导致异常:
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)
Run Code Online (Sandbox Code Playgroud)
任何想法都将受到欢迎
谢谢!维塔利
Vit*_*lyB 14
发布我从MSDN论坛获得的答案,由Ryan Molden提供,以防它帮助任何人:
我相信这里的问题是CLR如何处理COM端点(事件接收器).如果我在你的'链'的_applicationObject.Events.DebuggerEvents部分中正确回想起来,CLR将为属性访问创建一个新的DebuggerEvents对象,并且不会对它进行缓存,因此它会返回给你,你注册一个事件它的处理程序(由于委托,它在TEMPORARY对象和对象之间创建一个强引用,但不是从您的对象到临时对象,这将阻止GC).然后你不会将该对象存储在任何地方,因此它立即符合GC条件,最终将被GC.
我更改了代码以将DebuggerEvents存储为字段,并且它们都开始正常工作.
以下是@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...
}
Run Code Online (Sandbox Code Playgroud)