VSIX:获取DTE对象

我的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 – 它根本不会触发。

我在这看到几个问题:

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

请尝试以下命令:

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

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

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

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

我知道你已经选择了一个答案,但你确实指出你不想使用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(); } } }
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(); } } }