9

我的 Visual Studio 包需要使用 EnvDTE.DTE 变量,但它总是返回为 null。在阅读了许多 hack 之后,他们都说要使用 OnShellPropertyChange() 方法(IVsShellPropertyEvents),但有时它永远不会触发 - 就好像我的扩展永远不会完成加载一样。

我正在使用 VS2010 并检查 VSSPROPID_Zombie 和 ShellInitialized - 没有工作。:(

有任何想法吗?这是我正在使用的代码:

public int OnShellPropertyChange(int propid, object var) {
            if (propid == -9053 || (int) __VSSPROPID.VSSPROPID_Zombie == propid) { // -9053 = ShellInit
                try {
                    if ((bool) var == false) {
                        Dte = GetService(typeof (SDTE)) as DTE;
                        Flow.Dte = Dte;

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

                        if (shellService != null)
                            ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(_cookie));

                        _cookie = 0;
                    }
                } catch {

                }
            }

            return VSConstants.S_OK;
        }

编辑:在实验实例下,它工作得很好,初始化大约需要 5 秒。但是,一旦部署为 VSIX - 它根本不会触发。

4

4 回答 4

31

尝试以下命令:

dte = Package.GetGlobalService(typeof(DTE)) as DTE2;
于 2012-03-16T09:37:01.487 回答
6

如果您有一个 MEF 组件,那么获取DTE对象的最简单方法如下

首先添加对 Microsoft.VisualStudio.Shell.Immutable.10 的引用。然后为SVsServiceProvider. 这个对象有一个 GetService 方法,可以查询DTE

[ImportingConstructor]
public MyComponent(SVsServiceProvider serviceProvider) {
  _DTE dte = (_DTE)serviceProvider.GetService(typeof(_DTE));
}
于 2010-09-25T05:15:57.920 回答
5

我在这里看到几个问题:

  • 您确实应该使用 __VSSPROPID4.VSSPROPID_ShellInitialized (在 Microsoft.VisualStudio.Shell.Interop.10.0 中定义)而不是 -9083 以提高可读性
  • 您应该检查 ShellInitialized 是否设置为true(尽管检查 Zombie 是否为 false 是正确的)
  • 请记住,ShellInitialized 将在 VS 启动时更改为 true一次。如果您的包已注册为在启动时自动加载(这可能发生在 VS 完全准备就绪之前),那么检查它是正确的方法。但是,大多数包不应该启动时自动加载,而是根据需要您的包代码的某些用户操作按需加载。然后,您可以在包类 Initialize 方法中检查 DTE 服务。
于 2010-09-25T17:22:09.753 回答
3

我知道您已经选择了一个答案,但您确实指定您不想使用 MEF,所以我想我会发布一个替代方案,只是为了完整起见......;p


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using EnvDTE;
using EnvDTE80;

namespace DTETesting
{
    class Program
    {
        const string ACTIVE_OBJECT = "VisualStudio.DTE.10.0";
        static void Main(string[] args)
        {
            EnvDTE80.DTE2 MyDte;
            MyDte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject(ACTIVE_OBJECT);
            Console.WriteLine("The Edition is "+MyDte.Edition);
            Console.ReadLine();
        }
    }
}

于 2010-11-24T13:15:24.353 回答