为什么dte.MainWindow在VSIX Package Initialize方法中抛出NullRefEx?

时间:2014-09-19 17:44:11

标签: visual-studio envdte vsix vspackage

我正在将VS Addin转换为VS包。

我的VSIX Package类中有这个代码(派生自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

enter image description here

然后必须初始化某些东西。 我什么时候打电话给dte.MainWindow

在VS Addin中,当dte.MainWindow Addin类型中的public void OnStartupComplete(ref Array custom) {调用Connect时,它正在运行。

2 个答案:

答案 0 :(得分:1)

为了能够呼叫dte.MainWindow我找到了注册到事件dte.Events.DTEEvents.OnStartupComplete的选项。正如here所解释的那样,我需要保留对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!!
            ...
         };

答案 1 :(得分:0)

当DTE不为null但DTE.MainWindow在初始化我的MZ-Tools包时被调用时,我也看到了这个问题。我有待用最小的包重现它(几天前的快速尝​​试无法重现它)。

在终止程序包时获取DTE.MainWindow时我也看到了InvalidCastException,我还要重现:

  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作为父窗口。