2010-09-25 69 views
8

我的Visual Studio包需要使用EnvDTE.DTE变量,但始终返回为空。在阅读了很多黑客知识之后,他们都说要使用OnShellPropertyChange()方法(IVsShellPropertyEvents),但有时它永远不会触发 - 就好像我的扩展从未完成加载。VSIX:获取DTE对象

我使用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 - 它。根本不火。

回答

6

我看到一对夫妇的问题,这里的GetService方法:

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

VSSPROPID4给了我一些不明确的问题,这就是为什么我现在用整数。我会改变这种状况,看看它现在是否奏效 - 谢谢! – 2010-09-25 19:19:21

5

如果你有一个MEF组件,以获得最简单的方式为DTE对象如下

首先添加到Microsoft.VisualStudio.Shell.Immutable.10的参考。然后添加一个MEF进口SVsServiceProvider对象具有可用于查询DTE

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

虽然我没有MEF组件。任何想法,为什么财产永远不会改变?这是一个VS VMSDK项目。 – 2010-09-25 15:25:53

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(); 
     } 
    } 
} 
 
+0

整洁。谢谢:) – 2010-11-24 18:02:23

+0

也发现了这个,http://msdn.microsoft.com/en-us/library/68shb4dw%28v=VS.100%29.aspx – Terrance 2011-03-04 15:12:31

+0

请注意:如果您运行的Visual Studio的多个实例,这会让你成为其中的一员,但不一定是你正在运行的那个。 – RichieHindle 2013-03-14 23:18:05

23

请尝试以下命令:

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

这一个适用于我,只需在项目中添加对Microsoft.VisualStudio.Shell.dll的引用即可。 – 2012-07-01 21:24:44

+0

这也适用于我。我在XAML UI后面的代码中使用。 – 2014-06-05 10:23:18