VSIX:获取DTE对象

时间:2010-09-25 03:14:36

标签: c# .net visual-studio visual-studio-2010 vsix

我的Visual Studio包需要使用EnvDTE.DTE变量,但它总是返回null。在阅读了许多黑客之后,所有人都说要使用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 个答案:

答案 0 :(得分:25)

尝试以下命令:

dte = Package.GetGlobalService(typeof(DTE)) as DTE2;

答案 1 :(得分:6)

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

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

[ImportingConstructor]
public MyComponent(SVsServiceProvider serviceProvider) {
  _DTE dte = (_DTE)serviceProvider.GetService(typeof(_DTE));
}

答案 2 :(得分:6)

我在这里看到了几个问题:

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

答案 3 :(得分: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();
        }
    }
}