2010-10-06 1 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
  • не Сохранение документа

Ни один из них, кажется, никакого эффекта и функции обратного вызова были никогда не вызывал.

Вторая проблема заключается в том, что подписка на линию событий работает УСПОЛЬЗОВАТЬ (сама подписка, обратный вызов не работает, как описано выше) но через некоторое время запуска подписки линию, например:

_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, Райан Molden, в случае, если это поможет кому:

Я считаю, что проблема здесь как CLR обрабатывает COM конечные точки (события раковины) , Если я правильно помню, когда вы попали в _applicationObject.Events.DebuggerEvents части вашей «цепочки» в CLR будет создать новый DebuggerEvents объект для в плане доступа свойства и не кэшировать его, для этого он возвращается к вам вы регистрация обработчик событий к нему (которому создает сильный реф между вРЕМЕННЫМ объектом и вашим объектом из-за делегата, но не с вашего объекта на временный объект, который бы предотвратить GC). Тогда вы не сохраните этот объект в любом месте, так что это немедленно GC имеет право и будет в конечном итоге GC.

Я изменил код, чтобы сохранить DebuggerEvents как поле, и все это начало работать нормально.

+0

Я была такая же проблема, и это решает ее. Благодаря! –

+0

Вы спасли 2 дня моей работы. Внутри моей упаковки: 'private static SolutionEvents solutionEvents; protected override void Initialize() { ApplicationObject = GetService (typeof (DTE)) как DTE2; solutionEvents = ApplicationObject.Events.SolutionEvents;} ' – LukTar

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

} 

 Смежные вопросы

  • Нет связанных вопросов^_^