Начало Получить ссылку на VS
Я предлагаю реализовать это как метод, который будет принимать
DTE (главный объект в модели автоматизации студии) версию и флаг, который будет показывать
запущена студия или нет.
copy to clipboardподсветка кода- (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.9.0")
Этот код применим для VS2008. Если вы захотите установить свои компоненты в несколько студий, я советую создать нумератор, где
будут перечислены все возможные варианты.
copy to clipboardподсветка кода- [Flags]
- public enum DTEVersion
{ - None = 0x0000,
- [Description("VisualStudio.DTE.9.0")]
- VS2008 = 0x0001,
- [Description("VisualStudio.DTE.8.0")]
- VS2005 = 0x0002,
- [Description("VisualStudio.DTE.7.0")]
- VS2003 = 0x0004,
- [Description("VisualStudio.DTE.10.0")]
- VS2010 = 0x0008,
- }
Использование нумераторов делает код более гибким. Можно не делать проверку на соответствие строк, к тому же RegisterControls так
же может принимать DTEVersion. Внутри метода RegisterControls можно будет написать тогда так:
copy to clipboardподсветка кода- public static void RegisterControls(DTEVersion dteVersion, params VSControl[] controls) {
- DTE2 dte = null;
- var alreadyCreated = false;
-
- if ((dteVersion & DTEVersion.VS2008) > DTEVersion.None) {
- dte = (DTE2)
Marshal.GetActiveObject("VisualStudio.DTE.9.0"); - // other code
- ...
- }
-
- if ((dteVersion & DTEVersion.VS2010) > DTEVersion.None) {
- dte = (DTE2)
Marshal.GetActiveObject("VisualStudio.DTE.10.0"); - // other code
- ...
- }
- }
Появление в коде строковых переменных весьма странно, когда уже есть нумератор с описаниями. И вот способ как это можно
использовать:
copy to clipboardподсветка кода- internal static string GetEnumDescription(Enum value) {
- var fieldInfo = value.GetType().GetField(value.ToString());
- var attributes = (DescriptionAttribute[])
fieldInfo.GetCustomAttributes(typeof
(DescriptionAttribute), false); - return (attributes.Length > 0) ? attributes
[0].Description : value.ToString
(); - }
И тогда получение ссылки на студию
copy to clipboardподсветка кода- dte = (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.9.0");
можно переписать следующим образом:
copy to clipboardподсветка кода- dte = GetDesignTimeEnvironment(DTEVersion.VS2008, ref alreadyCreated);
в новом методе мы проверим еще кое-что. Когда вы получаете DTE2, это занимает некоторое время для того, чтобы СОМ-метод вызвался и
вернул результат. После этого, было бы неплохо проверить, что ссылка на студию действительно получена, и попробовать переключится
на какой-нибудь базовый экран, к примеру, на окно свойств.
copy to clipboardподсветка кода- public static DTE2 GetDesignTimeEnvironment
(DTEVersion dteVersion, ref bool alreadyCreated)
{ - alreadyCreated = false;
-
- var progID = GetEnumDescription
(dteVersion); - DTE2 result;
-
- try {
- result = (DTE2)
Marshal.GetActiveObject(progID); - Thread.Sleep(5000);
- try {
- result.ExecuteCommand("View.PropertiesWindow", "");
- alreadyCreated = true;
- }
- catch {
- result = null;
- }
- }
- catch { //There is no open VS.Net
- result = null;
- }
-
- return result;
- }
Осталось проверить результат на null и если не null, то создаем новую панель.
Получение указателя на панель инструментов
Вы будете удивлены, но это очень легко! Всего 2 строчки кода.
copy to clipboardподсветка кода- var toolbox = dte.Windows.Item(Constants.vsWindowKindToolbox);
- var tabs = ((ToolBox)
toolbox.Object).ToolBoxTabs;
Создание новой панели
Так как компоненты и новая панель уже должны быть обернуты в VSControl - новый метод должен принимать массив этого класса. Ищем в
массиве объявления панелей и создаем их.
copy to clipboardподсветка кода- internal static void RegisterControls(DTE2 dte, bool alreadyCreatedDTE, VSControl[] controls)
{ - var toolbox = dte.Windows.Item
(Constants.vsWindowKindToolbox); - var tabs = ((ToolBox)
toolbox.Object).ToolBoxTabs; - controls
- .ToList()
- .FindAll
(i => i.IsToolBoxTab) - .ForEach(i => {
- var tab =&nb
sp;GetToolBoxTab(tabs, i.TabName); - if (tab != null)
- &nbs
p;tab.Delete(); - tabs.Add
(i.TabName); - });
- }
-
- private static ToolBoxTab3 GetToolBoxTab(ToolBoxTabs tabs, string tabName) {
- foreach (ToolBoxTab3 tab in tabs) {
- if (smenglish.CompareInfo.Compare
(tab.Name, tabName, CompareOptions.IgnoreCase) == 0) - return tab;
- }
-
- return null;
- }
И поле класса:
copy to clipboardподсветка кода- internal static CultureInfo smenglish = CultureInfo.CreateSpecificCulture
("en");
Читать полностью на
Violet Tape или
часть III