2010-09-25 5 views
8

Mon package Visual Studio nécessite l'utilisation d'une variable EnvDTE.DTE, mais il revient toujours à zéro. Après avoir lu sur de nombreux hacks, tous disent d'utiliser la méthode OnShellPropertyChange() (IVsShellPropertyEvents), mais parfois il ne se déclenche jamais - comme si mon extension ne finissait jamais le chargement.VSIX: Obtention d'un objet DTE

J'utilise VS2010 et vérifie à la fois VSSPROPID_Zombie et ShellInitialized - pas de travail. ? :(

Toutes les idées Voici le code que je utilise:

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: En instance expérimentale, cela fonctionne parfaitement et prend environ 5 secondes pour initialiser Cependant, une fois déployé en tant que VSIX - il. tout simplement ne se déclenche pas.

Répondre

6

Je vois quelques problèmes ici:

  • Vous devriez vraiment utiliser __VSSPROPID4.VSSPROPID_ShellInitialized (défini dans Microsoft.VisualStudio.Shell.Interop .10.0) au lieu de -9083 pour une meilleure lisibilité
  • Vous devriez vérifier pour ShellInitialized être réglé sur vrai (bien que la vérification de Zombie va faux est correct)
  • Gardez à l'esprit que ShellInitialized deviendra une fois ... au démarrage de VS. La vérification est la bonne approche si votre paquet est enregistré pour le chargement automatique au démarrage (ce qui peut arriver avant que VS soit complètement prêt à partir). Cependant, la plupart des paquets ne devraient pas se charger automatiquement au démarrage, mais plutôt charger à la demande à partir d'une action de l'utilisateur nécessitant votre code de paquet. Vous pouvez ensuite vérifier le service DTE dans la méthode Initialize de la classe de package.
+0

VSSPROPID4 m'a donné quelques problèmes d'ambiguïté, c'est pourquoi je suis allé avec l'entier pour l'instant. Je vais changer la condition et voir si cela fonctionne maintenant - merci! –

5

Si vous avez un composant le plus simple MEF pour se rendre à un objet DTE est comme suit

d'abord ajouter une référence à Microsoft.VisualStudio.Shell.Immutable.10. Ensuite, ajoutez un MEF import pour SVsServiceProvider. objet a une méthode de GetService qui peut être interrogé pour DTE

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

Je n'ai pas un composant MEF cependant. Des idées sur pourquoi la propriété ne change jamais? C'est un projet VS VMSDK. –

3

Je sais que vous avez sélectionné une réponse déjà, mais vous ne spécifiez que vous ne vouliez utiliser le MEF, donc je pensais que je posterais une alternative juste pour être complet ....; 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

Neat. Merci :) –

+0

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

+0

Attention: si vous exécutez plusieurs instances de Visual Studio , ceci vous obtiendra l'un d'eux, mais pas nécessairement celui que vous courez dedans. – RichieHindle

23

Essayez la commande suivante:

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

Celui-ci fonctionne pour moi, il suffit d'ajouter une référence à Microsoft.VisualStudio.Shell.dll dans le projet. –

+0

Cela fonctionne pour moi aussi. J'utilise dans le code derrière l'interface utilisateur XAML. –

Questions connexes