Dr. eX: Why does GetService(typeof(EnvDTE.DTE)) return null?

Ever build a Visual Studio package with code that looks like the following?

protected override void Initialize()

{

base.Initialize();

            this.dte = GetService(typeof(DTE)) as DTE;

……

}

And then realize later on that this.dte is null?

A number of Visual Studio integrators have encountered just this problem in the past, and having recently seen this problem pop up again, it’s definitely past due for Dr. eX to blog about this.

The reason the above GetService call can sometimes return null, is due to the environment not being fully loaded and initialized. When the IDE is in this state it’s said to be in a “zombie” state. The IDE actually tracks this state with the VSPROPID_Zombie property.

To work around this problem, you simply need to defer the code in your Initialize method, until the VSPROPID_Zombie property has been set to false. To do this, your package should implement IVsShellPropertyChanges interface, and execute your initialization code from your IVsShellPropertyChanges.OnShellPropertyChange implementation. For example:

public class MyPackage : Package, IVsShellPropertyEvents

{

   DTE dte;

   uint cookie;

 

   protected override void Initialize()

   {

      base.Initialize();

 

      // set an eventlistener for shell property changes

      IVsShell shellService = GetService(typeof(SVsShell)) as IVsShell;

      if (shellService != null)

         ErrorHandler.ThrowOnFailure(shellService.AdviseShellPropertyChanges(this,out cookie));

 

      // code not depending on zombie state

      ……..

   }

 

   public int OnShellPropertyChange(int propid, object var)

   {

      // when zombie state changes to false, finish package initialization

      if ((int)__VSSPROPID.VSSPROPID_Zombie == propid)

      {

         if ((bool)var == false)

         {

            // zombie state dependent code

            this.dte = GetService(typeof(SDTE)) as DTE;

 

            // eventlistener no longer needed

            IVsShell shellService = GetService(typeof(SVsShell)) as IVsShell;

            if (shellService != null)

               ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(this.cookie));

            this.cookie = 0;

         }

      }

      return VSConstants.S_OK;

   }

}

Happy coding,
Dr. eX