VSIX:获取DTE对象

10
我的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个回答

32

尝试以下命令:

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

3
这个对我有用,只需要在项目中添加对Microsoft.VisualStudio.Shell.dll的引用。 - Scott Mackay
这对我也有效。我在 XAML UI 的代码后端使用它。 - Farrukh Waheed

6
如果你有一个MEF组件,最简单的方法获取DTE对象如下:
首先添加对Microsoft.VisualStudio.Shell.Immutable.10的引用。然后为SVsServiceProvider添加一个MEF导入。这个对象有一个GetService方法,可以查询DTE。
[ImportingConstructor]
public MyComponent(SVsServiceProvider serviceProvider) {
  _DTE dte = (_DTE)serviceProvider.GetService(typeof(_DTE));
}

我没有MEF组件。你们有什么想法为什么属性从未改变?这是一个VS VMSDK项目。 - hb.

6
我看到这里有几个问题:
  • 为了更易读,你应该使用__VSSPROPID4.VSSPROPID_ShellInitialized(在Microsoft.VisualStudio.Shell.Interop.10.0中定义)而不是-9083。
  • 你应该检查ShellInitialized是否设置为true(虽然检查Zombie变为false是正确的)。
  • 请记住,ShellInitialized将在VS启动时更改为true一次。如果您的包已注册以自动加载启动(可能会在VS完全准备好之前发生),则检查它是正确的方法。但是,大多数包都不应该在启动时自动加载,而是根据某些需要您的包代码的用户操作按需加载。然后可以在包类Initialize方法中检查DTE服务。

VSSPROPID4 给我带来了一些歧义问题,所以我现在选择了整数。我会更改条件并查看是否可以正常工作 - 谢谢! - hb.

3

我知道你已经选择了一个答案,但是你指定你不想使用MEF,所以我想为了完整性而发布一个替代方案...


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) { // 获取 Visual Studio 对象。 EnvDTE80.DTE2 MyDte; MyDte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject(ACTIVE_OBJECT); Console.WriteLine("版本是 "+MyDte.Edition); Console.ReadLine(); } } }

我也找到了这个链接:http://msdn.microsoft.com/en-us/library/68shb4dw%28v=VS.100%29.aspx - Terrance
2
注意:如果您正在运行多个 Visual Studio 实例,则此代码将获取其中一个实例,但不一定是您正在使用的那个。 - RichieHindle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接