【问题标题】:Why dte.MainWindow throw a NullRefEx in VSIX Package Initialize method?为什么 dte.MainWindow 在 VSIX 包初始化方法中抛出 NullRefEx?
【发布时间】:2014-09-19 17:44:10
【问题描述】:

我正在将 VS 插件转换为 VS 包。

我的 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 插件中,当 public void OnStartupComplete(ref Array custom) {Connect 插件类型中调用 dte.MainWindow 时,它正在工作。

【问题讨论】:

  • 那个 Debug.Assert() 让你睡着了。无论如何,它绝对不会告诉你一些你不会很快发现的事情。这是有害的,删除它。让你头脑清醒,你现在就来看看dte
  • 该问题与 Debug.Assert(...) Hans 无关。顺便说一句,它告诉我一些非常有用的东西:感谢这个断言,我知道 dte 不是 null,因此 NullRefEx 在调用 get_MainWindow() 期间来自 null。
  • 通向神秘问题的道路是由假设铺成的。我们不知道的是 _DEBUG 条件是否真的被定义了。一切都说不是。
  • 汉斯,问题不是来自 Debug.Assert(),是的,代码是在调试模式下编译的,我确实可以准确地说。
  • 刚刚更新了问题,让我们专注于问题本身。

标签: visual-studio envdte vsix vspackage


【解决方案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!!
            ...
         };

【讨论】:

    【解决方案2】:

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

    在终止包时获取 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 作为父窗口。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-08
    • 1970-01-01
    • 1970-01-01
    • 2012-09-30
    • 2019-03-31
    • 1970-01-01
    • 2021-08-03
    • 2013-12-31
    相关资源
    最近更新 更多