VSIX: получение объекта DTE - PullRequest
       8

VSIX: получение объекта DTE

9 голосов
/ 25 сентября 2010

Мой пакет Visual Studio требует использования переменной EnvDTE.DTE, но он всегда возвращается как ноль. После прочтения многих хаков все они говорят, что используют метод 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 он просто не запускается.

Ответы [ 4 ]

25 голосов
/ 16 марта 2012

Попробуйте следующую команду:

dte = Package.GetGlobalService(typeof(DTE)) as DTE2;
6 голосов
/ 25 сентября 2010

Я вижу здесь несколько проблем:

  • Вы действительно должны использовать __VSSPROPID4.VSSPROPID_ShellInitialized (определено в Microsoft.VisualStudio.Shell.Interop.10.0) вместо -9083 для удобства чтения
  • Вы должны проверить, что для ShellInitialized установлено значение true (хотя проверка на Zombie имеет значение false - правильна)
  • Имейте в виду, что ShellInitialized изменится на true один раз ... при запуске VS.Проверять это - правильный подход, если ваш пакет зарегистрирован для автоматической загрузки при запуске (что может произойти до того, как VS будет полностью готов к работе).Однако большинство пакетов должны не автоматически загружаться при запуске, а загружаться по требованию от некоторых действий пользователя, требующих кода вашего пакета.Затем вы можете проверить наличие службы DTE в классе Initialize класса вашего пакета.
6 голосов
/ 25 сентября 2010

Если у вас есть компонент MEF, проще всего добраться до объекта DTE следующим образом:

Сначала добавьте ссылку на Microsoft.VisualStudio.Shell.Immutable.10. Затем добавьте импорт MEF для SVsServiceProvider. Этот объект имеет метод GetService, который может быть запрошен для DTE

[ImportingConstructor]
public MyComponent(SVsServiceProvider serviceProvider) {
  _DTE dte = (_DTE)serviceProvider.GetService(typeof(_DTE));
}
3 голосов
/ 24 ноября 2010

Я знаю, что вы уже выбрали ответ, но указали, что не хотите использовать 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();
        }
    }
}

...