Установка самописных компонентов

После того, как вы сделали собственные визуальные компоненты, я думаю, вы захотите их использовать в различных проектах, а впоследствии и поделится с миром наработками. Как их установить на панель инструментов в студии, как добавить эту библиотеку в “Add reference…” диалог и как избежать подводных камней в этом деле – все это будет описано в этой статье.

Подготовка сборки (assembly)

Когда у вас есть проект с настроенными компонентами и вы чувствуете что они выглядят и работают точно так как вам хочется – вы, возможно, захотите автоматизировать процесс установки. Для этого потребуется:

  1. Подписать сборку;
  2. Установить сборку в GAC;
  3. Добавить  в “Add reference…” диалог;
  4. Добавить в панель инструментов студии.

Далее я расскажу как автоматизировать почти все пункты из этого списка, в небольших примерах. Для дальнейшего повествования буду исходить их предположения, что библиотека с компонентами зовется myCustomControl.dll.

Вообще, подписать сборку более чем легко. Вызываете контекстное меню для проекта, выбираете пункт Properties. Далее выбираем закладку Signing. Ставим галочку напротив “Sign the assembly” и выпадающий список будет доступен для редактирования.

Выбираем пункт “<New…>”, заполняем поля в появившемся окне и жмем OK. Пересобираем приложение. Вот и все. Только что создали подпись (strong key) для сборки.

Следующим шагом будет…

Добавление в GAC

Думаю, что более подходящим способом будет использование утилиты gacutil.exe. Ее можно вызвать из Visual Studio Command Prompt следующим образом:

gacutil /i “c:\my controls\myCustomControl.dll”

Незабываем, что путь надо писать в кавычках, если он содержит пробелы. Эта операция добавит сборку в GAC. В нашем случае, в программе я использую ключ /if (install force) для того, чтобы переписать сборку, если она уже есть. Код ниже, автоматизирует вызов утилиты:

Gacutil распространяется с .NET SDK. Для версии 3.5 путь C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\gacutil.exe; 4.0 – C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bin\gacutil.exe. Принимая во внимание только что сказанное:

В процессе выполнения может мелькнуть окно консоли и все. Сборка в GAC. Для того, чтобы удалить вашу библиотеку из GAC, надо выполнить команду с ключом  “/u” и добавить “f” если надо эту операцию сделать принудительно.

Добавление в диалог “Add reference…” в Visual Studio

Большинство моих коллег думают, что достаточно добавить библиотеку в GAC, как она тут же появится в вышеозначенном окне. К сожалению это не так, добавление в GAC это лишь один из шагов. Необходимо добавить еще ключ в реестре.

Цель:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders.

По этому пути надо создать ключ с точно таким же именем, как и библиотека, но без dll. После всех действий должно получится как на картинке:

Теперь, как это провернуть с помощью кода:

Для удаления – просто сотрите ключ из реестра.

Добавление в панель инструментов Visual Studio

Самые странные и уму непостижимые вещи начинаются здесь. Большинство из них из-за COM прошлого студии, некоторые появляются без вообще какого бы то ни было логического объяснения.  Ну ладно, начнем с дурацких ограничений, которые могут всплыть.

  • Если у вас стоит AnkhSVN, то это может привести к СОМ ошибкам. Я пробовал создавать закладки для панели инструментов на Win7 (7100) и получал ошибку, пока не снес этот плагин для студии. Под ХР все работает отлично даже с AnkhSVN. Описанную проблему можно найти на форуме Infragistics – у них та же проблема с AnkhSVN; и на собственном форуме этого плагина, но без описания почему это происходит и есть ли какое-нибудь лекарство. Так что помните об этом.
  • Новая закладка с компонентами может быть установлена только тогда, когда WinForm проект существует в текущем открытом солюшене. Иначе только пустая закладка появится. К счастью, это легко обходится программным путем и я покажу как это сделать.

Перед началом написания кода необходимо добавить проектные ссылки на:

  • EnvDTE;
  • EnvDTE80;
  • EnvDTE90.

От винта!

Установка при запущенной студии

В целом, при запущенной студии, достаточно легко работать. Для этого случая я буду предполагать, что солюшен с WinForm проектом все же существует и загружен. Ну или зачем тогда устанавливать визуальные компоненты? ;)

Первым делом надо определиться с тем, что мы будем устанавливать в новую панель, и новую панель тоже надо как-то идентифицировать. Для этой задачи создадим класс-помощник VSControl. Этот класс будет содержать информацию об имени новой панели, пути к сборке, типе компонента. Так же нам потребуется 2 конструктора: один для панели,

и второй для элементов на нем. Выглядит сложновато, но конечная цель – более легкий код в дальнейшем. Я думаю что тут можно избавиться от assemblyPath и использовать взамен assembly.Location.

Следующие действия:

  1. Получить ссылку на VS;
  2. Получить ссылку на панель инструментов;
  3. Создать новую панель;
  4. Создать набор компонентов.

Все эти действия, на мой взгляд, лучше всего собрать под крышей одного класса DevEnvironment. Этот класс будет иметь только один публичный метод, к примеру, RegisterControls, который будет принимать в качестве параметров массив компонентов и номер версии студии.

В деталях это все будет:

Получить ссылку на VS

Я предлагаю реализовать это как метод, который будет принимать DTE (главный объект в модели автоматизации студии) версию и флаг, который будет показывать запущена студия или нет.

Этот код применим для VS2008. Если вы захотите установить свои компоненты в несколько студий, я советую создать нумератор, где будут перечислены все возможные варианты.

Использование нумераторов делает код более гибким. Можно не делать проверку на соответствие строк, к тому же RegisterControls так же может принимать DTEVersion. Внутри метода RegisterControls можно будет написать тогда так:

Появление в коде строковых переменных весьма странно, когда уже есть нумератор с описаниями. И вот способ как это можно использовать:

И тогда получение ссылки на студию

можно переписать следующим образом:

в новом методе мы проверим еще кое-что. Когда вы получаете DTE2, это занимает некоторое время для того, чтобы СОМ-метод вызвался и вернул результат. После этого, было бы неплохо проверить, что ссылка на студию действительно получена, и попробовать переключится на какой-нибудь базовый экран, к примеру, на окно свойств.

Осталось проверить результат на null и если не null, то создаем новую панель.

Получение указателя на панель инструментов

Вы будете удивлены, но это очень легко! Всего 2 строчки кода.

Создание новой панели

Так как компоненты и новая панель уже должны быть обернуты в VSControl – новый метод должен принимать массив этого класса. Ищем в массиве объявления панелей и создаем их.

И поле класса:

Создание новых компонентов

Теперь, когда созданы панели для новых компонентов, время создать реальные объекты. Для этого надо активировать соответствующую панель и создать элемент. Тоже не тяжело. Добавляем этот код после создания панелей.

Здесь есть небольшие нюансы: когда добавляете новый элемент с помощью кода tab.ToolBoxItems.Add, второй параметр – объект. Если передать строку, то она будет распознана как путь до сборки и все публичные компоненты оттуда будут добавлены. Если передать тип, то только этот объект будет добавлен.

Когда программа закончит добавлять компоненты к панели(ям), надо будет закрыть соединение c DTE2.

Вот и всё, для случая запущенной студии.

Установка при незапущенной студии

Думаю, что вам не захочется просить пользователя запустить Visual Studio и создать проект WinForm, перед тем как запустить установщик. И далее будет описано, как сделать это все автоматически.

Для начала нам надо создать новый экземпляр студии, для того чтобы продолжить работу. Думаю, что лучшим местом для этого куска кода будет метод GetDesignTimeEnvironment.

Как я уже ранее говорил, необходимо создать WinForm проект для того, чтобы все нормально установить. И это возможно сделать кодом тоже. Открываем метод RegisterControls и добавляем в начало.

На мой взгляд код тут самодокументирующийся и в комментариях не нуждается. Но не забываем закрыть солюшен перед концом программы.

Параметр является ответом на вопрос, сохранять проект или нет.

Теперь новые компоненты будут установлены независимо от того, запущена студия или нет. К сожалению СОМ ошибки могут нарушить всю идиллию. Во время разработки я получал тонны ошибок, которые сообщали, что СОМ-объект все еще занят и не может быть вызван. Поиски в интернете дали ответ на то, как это избежать.

Как избежать СОМ ошибок

Основная идея в том, чтобы отфильтровывать сообщения от СОМ-объектов и получать только те, на которые мы подпишемся.

Необходимо объявить интерфейс IOleMessageFilter

И сделать реализацию к нему.

В итоге должно получиться что-то в духе:

С этим кодом все у вас будет в ажуре!  =)

Я тестировал на семерке, ХР и все работало замечательно. Я надеюсь получить ваши комментарии, вопросы, предложения. Кстати да, в процессе написания я заметил места, где можно улучшить код, но оставил его до лучших времен.

Source code

Hard’n’heavy!

2 комментарий на “Установка самописных компонентов

  1. Спасибо за статью, получилось очень подробно!

    Может я чего-то не понимаю, но нельзя ли выполнить данную задачу проще?
    В процессе установки запускать студию, создавать WinForm проект, добавлять Tab в ToolBox.. по моему это как-то слишком сложно…

    Может данную задачу поможет решить Toolbox Controls Installer? (http://msdn.microsoft.com/ru-ru/library/bb286995%28v=VS.80%29.aspx)

    • Да, наверно может решить. Но на тот момент я до этого кажется не докопался. ))

Оставить комментарий