Почему dte.MainWindow генерирует NullRefEx в методе инициализации пакета VSIX?

Я конвертирую VS Addin в VS Package.

У меня есть этот код в моем классе пакета VSIX (который является производным от Microsoft.VisualStudio.Shell.Package)

  protected override void Initialize() {
     base.Initialize();

     var dte = this.GetService<DTE>() as DTE2;
     if(dte != null) {
        var x = dte.MainWindow;

Однако вызов dte.MainWindow в этом контексте вызывает NullReferenceException.

введите описание изображения здесь

Тогда что-то инициализировать нельзя. Когда тогда мне следует позвонить dte.MainWindow?

В VS Addin это работало, когда dte.MainWindow был вызван из public void OnStartupComplete(ref Array custom) { в типе Connect Addin.


person Patrick from NDepend team    schedule 19.09.2014    source источник
comment
Этот Debug.Assert () усыпит вас. Он абсолютно ничего не говорит вам о том, что вы все равно не узнаете очень скоро. Это вредно, удалите. Очищает ваш разум, теперь вы посмотрите на dte.   -  person Hans Passant    schedule 19.09.2014
comment
Вопрос не имеет отношения к Debug.Assert (...) Hans. И, кстати, он сообщает мне кое-что очень полезное: благодаря этому утверждению я знаю, что dte не является нулевым, поэтому NullRefEx исходит из чего-то нулевого во время вызова get_MainWindow ().   -  person Patrick from NDepend team    schedule 19.09.2014
comment
Путь к мистическим проблемам вымощен предположениями. Мы не знаем, действительно ли определено условие _DEBUG. Все говорит, что это не так.   -  person Hans Passant    schedule 19.09.2014
comment
Ганс, проблема не в Debug.Assert (), и да, код скомпилирован в режиме отладки, и я действительно мог бы это уточнить.   -  person Patrick from NDepend team    schedule 19.09.2014
comment
Просто обновил вопрос, чтобы сосредоточиться на самой проблеме.   -  person Patrick from NDepend team    schedule 19.09.2014


Ответы (2)


Чтобы иметь возможность позвонить dte.MainWindow, я нашел возможность зарегистрироваться на событие dte.Events.DTEEvents.OnStartupComplete. Как объяснялось здесь, мне нужно сохранить ссылку на объект DTEEvents, чтобы избежать его отбрасывания.

  DTEEvents m_EventsObj;

  protected override void Initialize() {
     base.Initialize();

     var dte = this.GetService<DTE>() as DTE2;
     if(dte != null) {

        m_EventsObj = dte.Events.DTEEvents;
        m_EventsObj.OnStartupComplete += delegate {
            var mainWindow = dte.MainWindow; // <-- it works!!
            ...
         };
person Patrick from NDepend team    schedule 22.09.2014

Я также видел эту проблему, когда DTE не равно нулю, но DTE.MainWindow имеет значение null, если вызывается при инициализации моего пакета MZ-Tools. Я ожидаю воспроизвести его с минимальным пакетом (быстрая попытка несколько дней назад не смогла воспроизвести его).

Я также видел исключение InvalidCastException при получении DTE.MainWindow при завершении пакета, которое я также должен воспроизвести:

  private WindowEx GetMainWindowEx()
  {
     EnvDTE.Window mainWindow = null;
     WindowEx mainWindowEx = null;

     try
     {
        mainWindow = m_dte.MainWindow;
     }
     catch (InvalidCastException)
     {
        // This can happen in the case of a package after the IDE is closed that needs to show a MessageBox
     }
     catch (NullReferenceException)
     {
        // This can happen in the case of a package loaded before the IDE is initialized that needs to show a MessageBox
     }

     if (mainWindow != null)
     {
        mainWindowEx = new WindowEx(m_plugIn, mainWindow);
     }
     return mainWindowEx;
  }

В моем случае мне нужно только MainWindow, чтобы получить его дескриптор (hwnd) в качестве родительского для окон сообщений, которые в очень редких случаях должны отображаться во время инициализации / завершения, и если это не удается, я могу использовать null в качестве родительского окна.

person Carlos Quintero    schedule 19.09.2014
comment
Я говорю по телефону, поэтому не могу проверить себя, но происходит ли это после того, как VS больше не находится в состоянии зомби? например ваш собственный mztools.com/articles/2013/MZ2013029.aspx - person Igal Tabachnik; 20.09.2014