2010-10-06 26 views
11

Tôi đã thực hiện một phần mở rộng bên trong một gói và tôi đang gọi mã sau đây (xảy ra khi người dùng nhấn một nút trên thanh công cụ):Đăng ký các sự kiện DTE dường như không hoạt động - Sự kiện không được gọi là

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) 
{ 
} 

Vấn đề đầu tiên và chính là đăng ký sự kiện không hoạt động. Tôi đã thử:

  • Mở tài liệu mới
  • Tách gỡ lỗi (do đó được cho là gây ra OnEnterDesignMode
  • Lưu một tài liệu

Không ai trong số những dường như có bất kỳ tác dụng và các chức năng gọi lại là Không bao giờ được gọi là

Vấn đề thứ hai là đăng ký với sự kiện hoạt động bình thường (bản thân đăng ký, gọi lại không hoạt động như mô tả ở trên) nhưng sau một thời gian chạy dòng thuê bao, ví dụ:

_dte.Events.DebuggerEvents.OnEnterBreakMode -= DebuggerEvents_OnEnterBreakMode; 

Nguyên nhân một ngoại lệ:

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) 

Bất kỳ ý tưởng sẽ được chào đón

Cảm ơn! Vitaly

Trả lời

13

đăng một answer mà tôi nhận được từ các diễn đàn MSDN, bởi Ryan Molden, trong trường hợp nó giúp mọi người:

Tôi tin rằng vấn đề ở đây là cách CLR xử lý các điểm cuối COM (sự kiện bồn) . Nếu tôi nhớ chính xác khi bạn nhấn _applicationObject.Events.DebuggerEvents một phần của 'xích' của bạn CLR sẽ tạo DebuggerEvents MỚI đối tượng cho việc tiếp cận tài sản và SẼ KHÔNG bộ nhớ cache nó, do nó trở lại với bạn , bạn đăng ký một trình xử lý sự kiện cho nó (trong đó tạo một sự thay đổi mạnh mẽ giữa đối tượng TEMPORARY và đối tượng của bạn là cho đại biểu, nhưng KHÔNG từ đối tượng của bạn tới đối tượng tạm thời, sẽ ngăn GC). Sau đó, bạn không lưu trữ đối tượng đó ở bất kỳ đâu để nó là ngay lập tức GC đủ điều kiện và sẽ cuối cùng được GC'ed.

Tôi đã thay đổi mã để lưu trữ DebuggerEvents dưới dạng một trường và tất cả bắt đầu hoạt động tốt.

+0

tôi đã cùng một vấn đề và điều này giải quyết nó. Cảm ơn! –

+0

Bạn đã lưu 2 ngày làm việc. Bên trong gói của tôi: 'private static SolutionEvents solutionEvents; void ghi đè được bảo vệ Khởi tạo() { ApplicationObject = GetService (typeof (DTE)) làm DTE2; solutionEvents = ApplicationObject.Events.SolutionEvents;} ' – LukTar

8

Đây là những gì @VitalyB nghĩa sử dụng mã:

// 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... 

} 
Các vấn đề liên quan