2010-09-25 66 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