Patrick from NDepend team
Patrick from NDepend team

Reputation: 13842

Why dte.MainWindow throw a NullRefEx in VSIX Package Initialize method?

I am converting a VS Addin to a VS Package.

I have this code in my VSIX Package class(that derives from Microsoft.VisualStudio.Shell.Package)

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

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

However calling dte.MainWindow in this context throws a NullReferenceException.

enter image description here

Something must not be initialized then. When am I supposed to call dte.MainWindow then?

In the VS Addin it was working when dte.MainWindow was called from public void OnStartupComplete(ref Array custom) { in the Connect Addin type.

Upvotes: 1

Views: 379

Answers (2)

Patrick from NDepend team
Patrick from NDepend team

Reputation: 13842

To be able to call dte.MainWindow I found the option to register to event dte.Events.DTEEvents.OnStartupComplete. As explained here, I need to keep a reference to the DTEEvents object to avoid getting it discarded.

  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!!
            ...
         };

Upvotes: 1

Carlos Quintero
Carlos Quintero

Reputation: 4414

I have also seen that issue when DTE is not null but DTE.MainWindow is null if called when initializing my MZ-Tools package. I have pending to reproduce it with a minimal package (a quick attempt a few days ago was not able to reproduce it).

I have also seen an InvalidCastException when getting DTE.MainWindow when terminating the package, which I have also to reproduce:

  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;
  }

In my case I only need the MainWindow to get its handle (hwnd) as parent for message boxes that in very rare cases must be shown during initialization/termination and if it fails I can use null as parent window.

Upvotes: 0

Related Questions