2010-09-25 12 views
8

Mein Visual Studio-Paket erfordert die Verwendung einer EnvDTE.DTE -Variable, aber es wird immer als Null zurückgegeben. Nach dem Lesen vieler Hacks sagen alle von ihnen, dass sie die OnShellPropertyChange() Methode (IVsShellPropertyEvents) verwenden sollen, aber manchmal wird sie nie ausgelöst - als ob meine Erweiterung niemals fertig geladen wäre.VSIX: Abrufen des DTE-Objekts

Ich benutze VS2010 und Prüfung gegen VSSPROPID_Zombie und ShellInitialized - keine Arbeit. ? :(

Irgendwelche Ideen Dies ist der Code Ich verwende:

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; 
     } 

EDIT: Unter Experimental Instanz, es funktioniert perfekt und dauert ca. 5 Sekunden zu initialisieren Sobald jedoch als VSIX eingesetzt - es. einfach nicht ausgelöst.

Antwort

6

ich ein paar Probleme hier sehen:

  • Sie sollten wirklich __VSSPROPID4.VSSPROPID_ShellInitialized werden (definiert in Microsoft.VisualStudio.Shell.Interop .10.0) anstelle von -9083 zur besseren Lesbarkeit
  • Sie sollten für ShellInitialized werden zu überprüfen, wahr gesetzt wird (obwohl die Überprüfung für Zombie auf falsch gehen richtig ist)
  • Denken Sie daran, dass ShellInitialized sich beim Starten von VS auf ... ändern wird. Dies zu prüfen, ist der richtige Ansatz, wenn Ihr Paket beim Start automatisch geladen wird (was passieren kann, bevor VS vollständig betriebsbereit ist). Allerdings sollten die meisten Pakete nicht automatisch beim Start laden, sondern laden Sie auf Abruf von einigen Benutzeraktionen, die Ihren Paketcode erfordern. Sie können dann in Ihrer Paketklasseninitialisierungsmethode nach dem DTE-Dienst suchen.
+0

VSSPROPID4 gab mir einige Mehrdeutigkeitsprobleme, weshalb ich mit der Ganzzahl vorerst ging. Ich werde den Zustand ändern und sehen, ob es jetzt funktioniert - danke! –

5

Wenn Sie eine MEF Komponente der einfachste Weg, um ein Objekt ist DTE erhalten haben, wie

folgt

zuerst einen Verweis auf Microsoft.VisualStudio.Shell.Immutable.10 hinzufügen. Dann fügen Sie ein MEF-Import für SVsServiceProvider Objekt verfügt über eine GetService Methode, die für abgefragt werden können DTE

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

ich aber keine MEF Komponente. Irgendwelche Ideen, warum sich die Immobilie nie ändert? Es ist ein VS VMSDK-Projekt. –

3

Ich weiß, dass Sie eine Antwort bereits ausgewählt, aber Sie haben angeben, dass Sie waren nicht am MEF verwenden möchten, so dachte ich, ich würde eine alternative Post nur der Vollständigkeit halber ....; 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

Ordentlich. Danke :) –

+0

auch gefunden, http://msdn.microsoft.com/en-us/library/68shb4dw%28v=VS.100%29.aspx – Terrance

+0

Vorsicht: wenn Sie mehr als eine Instanz von Visual Studio ausführen , das wird dir einen von ihnen bringen, aber nicht unbedingt den, in dem du gerade liegst. – RichieHindle

23

Versuchen Sie den folgenden Befehl ein:

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

Dieser funktioniert bei mir, ich muss nur einen Verweis auf Microsoft.VisualStudio.Shell.dll im Projekt hinzufügen. –

+0

Das funktioniert auch für mich. Ich verwende den Code hinter XAML UI. –