Расширение возможностей среды разработки Visual Studio .NET
Андрей Колесов
С появлением Microsoft Office 97 программисты, работающие с VB, оказались в странном положении — в офисных приложениях для настройки интерфейса и автоматизации самых разнообразных операций стал широко использоваться знакомый им VBA, но их собственный инструмент был лишен этой возможности. Точнее, для функционального расширения среды VB (а также VBA в офисных пакетах) можно было применять подключение надстроек COM Add-Ins, реализованных в виде DLL, но в ней никогда ранее не было механизма макросов.
Создание же COM Add-Ins — вовсе не тривиальная задача, хотя бы потому, что при этом нельзя было пользоваться отладочным инструментарием среды разработки (при создании COM Add-Ins для офисных приложений широко используются все те же макросы — сначала проект отлаживается в среде VBA, а потом уже к нему подключается специальный программный интерфейс и проект преобразуется в DLL). Получалось, что даже начинающий пользователь, работающий, например, с Word, мог легко автоматизировать выполнение часто встречающейся операции с помощью функции автоматической записи макроса — Macro Recorder, но в то же время даже опытному VB-программисту сделать это было достаточно сложно (в силу трудоемкости создания COM Add-Ins соответствующие средства расширения разрабатывались обычно в коммерческих целях специализированными фирмами).
С появлением Visual Studio .NET ситуация исправилась — в инструментарии появился механизм разработки и использования макросов. В целом его реализация похожа на то, что многим программистам знакомо по приложениям Microsoft Office, хотя и есть некоторые отличия, на которые мы обратим внимание по ходу статьи*.
*Многие материалы по теме "разработка в среде Microsoft Office", опубликованные,
в частности, на сайте http://www.microsoft.ru/offext/officedev,
будут полезны для изучения технологии написания макросов для VS.NET. Как это ни
парадоксально, но даже опытным разработчикам, которые впервые столкнулись с темой
автоматизации своей работы и настройкой IDE, лучше сперва изучить раздел "Для
начинающих". Стоит также обратить внимание на статьи в разделе "Создание комплексных
решений", где обсуждаются вопросы программного управления проектами.
Объектная модель среды разработки (IDE) базируется на корневом объекте Development Tools Extensibility (DTE), который находится в пространстве имен EnvDTE библиотек классов .NET Framework. Через него можно получить ссылки на все множество объектов, соответствующих отдельным элементам IDE, таким, как Windows, Documents, Solutions, Projects, Debugger и Events (рис. 1). Каждый из этих объектов позволяет обратиться в собственной иерархической системе объектов, коллекций, свойств, методов и событий. Многие из этих компонентов имеют перекрестные связи, поэтому доступ к тому или иному объекту можно получить несколькими путями. Эта система объектов позволяет обращаться практически к любым компонентам и функциям среды разработки VS.NET.
Рис. 1. Общая структура иерархической системы объектов среды разработки. Здесь представлена только небольшая часть основных объектов.
|
Подчеркнем, что вся объектная модель IDE — сугубо внутренняя. DTE — не COM-объект, он недоступен из внешних приложений, т. е. VS.NET (в отличие от, например, Word) не является ActiveX-сервером. Отметим также, что макросы можно писать только на VB.NET (для создания COM Add-Ins можно использовать любые языки, поддерживающие архитектуру COM). Таким образом получается, что освоить VB желательно всем, кто хочет автоматизировать свою работу в среде VS.NET с помощью макросов.
Знакомство с Macro Explorer
В числе прочих окон управления средой разработки VS.NET предлагает Macro Explorer. Открыть его можно с помощью команды меню Tools|Macros|Macro Explorer или нажатием Alt+F8. Это окно позволяет редактировать, запускать, удалять и создавать макросы. Общая последовательность работы соответствует иерархии компонентов — проект, модуль, макрос.
Открыв окно Macro Explorer (оно добавляется к окну Solution Explorer в виде вкладки), вы увидите три Macro-проекта (рис. 2), которые первоначально загружаются по умолчанию из каталога My DocumentsVisual Studio ProjectsVSMacros. Впоследствии вы можете создавать новые проекты, добавлять существующие, выгружать ненужные проекты, которые могут храниться в любом месте. Но обратите внимание — все установки управления проектами (например, список загруженных Macro-проектов) связаны с IDE, а не с отдельным VS-решением. В этой связи можно провести аналогию с Microsoft Office, в частности, с Word: в большинстве офисных приложениях Macro-проекты связаны с конкретными документами или шаблонами, являясь их составной частью. В VS.NET Macro-проекты хранятся в отдельных файлах двоичного формата с расширением VSMACROS.
Рис. 2. Структура Macro-проектов, подключенных к среде разработки VS.NET IDE.
|
Два открывшихся по умолчанию проекта, MacroProject1 и MyMacro, пустые, а проект Samples содержит пять модулей, каждый из которых включает набор макросов. Всего здесь несколько десятков макросов, которые можно использовать для изучения и практического применения. Каждый модуль содержит функции работы с отдельными объектами среды разработки (VSEditor — редактор кода, VSDebugger — отладчик и т. д.).
Чтобы познакомиться с работой макросов, выполните в среде VS.NET следующую процедуру:
- Создайте новый Windows-проект (мы будем работать далее с VB.NET).
- Откройте окно кода формы и установите курсор в начало процедуры Load.
- В окне Macro Explorer раскройте узел модуля VSEditor и последовательно запустите на выполнение (двойным щелчком мыши или сначала щелкнув название правой кнопкой, а потом выбрав Run) макросы NewCommentLine и InsertDateTime (их код приведен в листинге 1).
После этого в код программы у вас добавится строка:
' 26 Октябрь 2002 г. 18:07:25
Чтобы запускать макросы, совсем необязательно открывать окно Macro Explorer — для часто используемых операций можно установить ссылки в виде команд меню, кнопок панелей управления или "горячих" клавиш с помощью диалогового окна Tools|Customize (рис. 3). Настройка пользовательского интерфейса среды разработки VS.NET выполняется точно так же, как в офисных приложениях Microsoft.
Рис. 3. Настройка интерфейса VS.NET IDE с помощью окна Customize.
|
Среда разработки макросов
Для разработки макросов в VS.NET имеется специальная среда, которая открывается в отдельном окне с помощью команды Macros IDE меню Tools|Macros или при выполнении любой попытки редактирования макроса (рис. 4). Macros IDE — это та же основная среда VS IDE, но с усеченным набором функций. Посмотрим внимательнее на состав Macro-проекта (но сильно углубляться в детали все же не будем, так как это весьма многогранная тема).
Рис. 4. Среда разработки макросов — Macros IDE.
|
В окне Macro Explorer на рис. 2 в проекте Samples мы видели пять макромодулей. В среде Macro IDE в окнах Project Explorer и Class View (рис. 4) мы видим еще два дополнительных компонента — References (ссылки на внешние объекты, в том числе .NET Framework) и модуль обработки событий EnvironmentEvents. Последний содержит несколько групп событийных процедур, которые позволяют реагировать на операции, выполняемые в основной среде VS IDE. Например, группа DocumentEvents включает события DocumentOpening, DocumentClosing, DocumentClosed и DocumentSaved.
Мы можем расширить список внешних ссылок проекта, выполнив команду Add Reference. Появится знакомое диалоговое окно (рис. 5), но состав доступных компонентов здесь иной по сравнению с VS.NET. В частности, многие объекты .NET Framework тут отсутствуют (не говоря уже о COM-объектах), но появились некоторые другие специальные библиотеки классов.
Рис. 5. Подключение ссылок на библиотеки внешних объектов.
|
Стоит также обратить внимание на окно Object Browser (см. рис. 3). В списке объектов тут находятся не только ссылки, определенные в узле Reference, но и объекты (макросы, функции) загруженных Macro-проектов и системных библиотек классов. Здесь же можно получить детальную информацию об объектной модели каждой библиотеки, в частности EnvDTE.
В макросе NewCommentLine имеется обращение к функции LineOrientedCommentStart модуля Utilities этого же проекта. Но посмотрите — эта процедура присутствует в окне Class View среды Macro IDE, но отсутствует в Macro Explorer. Объясняется это очень просто: по определению макросом является только процедура типа Sub, в которой отсутствуют передаваемые аргументы. Соответственно, в Macro Explorer видны только макросы, а в Macro IDE — все модули и процедуры проекта.
Из каких элементов может состоять Macro-проект? Кроме обычных программных модулей в него могут также входить модули класса. Никаких визуальных компонентов, например, форм, такой проект содержать не может, в этом плане его возможности существенно слабее, чем у VBA-проектов в офисных приложениях и у COM Add-Ins для VS.NET.
Создание макросов
Самый простой метод создания макросов — использование метода записи. Режим записи временного макроса устанавливается командой Tools|Macros|Record Temporary Macro или нажатием Ctrl+Shift+R. При этом в Macro-проекте, который помечен как Set as Recording Project, создается новый модуль RecordingModule и макрос с именем TemporaryMacro. На экране появляется также панель инструментов Record.
Создадим макрос, который будет создавать в активном окне кода новый метод. Для этого введите с клавиатуры Public Sub MyMethod, а потом нажмите Enter. Закончим запись макроса, нажав на панели Record кнопку Stop Recording. В результате сформируется следующий код макроса:
Sub TemporaryMacro() DTE.ActiveDocument.Selection.LineDown() DTE.ActiveDocument.Selection.EndOfLine() DTE.ActiveDocument.Selection.NewLine() DTE.ActiveDocument.Selection.Text = "Public Sub MyMethod" DTE.ActiveDocument.Selection.NewLine() End Sub |
Имейте в виду, что запись всегда производится в макрос с фиксированным именем TemporaryMacro, хотя вы можете менять проекты, куда идет запись. Поэтому при начале новой записи макроса старое содержимое TemporaryMacro автоматически теряется без предупреждения. Поэтому сразу после окончания записи макроса и проверки его работоспособности лучше сразу его переименовать — это можно сделать как в Macro Explorer, так и в среде Macro IDE.
Запустите макрос TemporaryMacro, чтобы убедиться в его работоспособности. Затем немного модифицируйте "руками" код созданного макроса, чтобы он мог формировать процедуры с любым именем:
Sub CreateVBSub() Dim procname As String procname = InputBox("Введите имя процедуры:") If Len(procname) > 0 Then DTE.ActiveDocument.Selection.LineDown() DTE.ActiveDocument.Selection.EndOfLine() DTE.ActiveDocument.Selection.NewLine() DTE.ActiveDocument.Selection.Text _ = "Public Sub MyMethod" DTE.ActiveDocument.Selection.NewLine() End If End Sub |
На этом мы закончим наше первое знакомство с использованием макросов для автоматизации операций в среде VS.NET. В целом широкие возможности дополнительной среды Macro IDE представляются очень интересными и полезными, но для их освоения потребуется немало времени, так как описание среды в документации очень скудное. Приходится использовать тривиальный, но трудоемкий метод "проб и ошибок". Поэтому я подведу некоторые промежуточные итоги своих изысканий.
Использование иерархической модели объектов DTE предоставляет очень широкие возможности управления средой VS.NET IDE. Но освоение среды — в силу обилия ее компонентов — потребует времени. На первом этапе хорошим подспорьем будут примеры, содержащиеся в Macro-проекте Samples. Весьма перспективным представляется использование событийных предопределенных макросов модуля EnvironmentEvents, которые позволяют автоматически выполнять нужные операции в процессе разработки решений в среде VS.NET IDE.
В целом разработка макросов в VS.NET похожа на аналогичную процедуру в Microsoft Office. Но очевидно, что пока возможности VS.NET при создании сложных макросов заметно слабее. Например, сейчас здесь нет возможности применения форм, элементов управления, внешних COM-объектов и т. д. Среда Macro IDE не является контейнером ActiveX, из нее нельзя, например, обращаться к тем же офисным приложениям.
Метод создания макросов с помощью Macro Recorder очень прост, но, к сожалению, некоторые мои макросы, созданные таким образом, не хотели работать: выдавались сообщения о неверном использовании команд, о конфликтах потоков и т. п. Возможно, для их устранения нужно более точное управление установками среды, но вполне вероятно, что есть какие-то дефекты самого VS.NET (не будем забывать — ведь это версия 1.0!).
Применение COM Add-Ins
Как уже отмечалось в начале статьи, для автоматизации работы в среде VS.NET IDE можно использовать расширения в виде COM Add-Ins. Их создание выглядит несколько более сложным по сравнению с созданием макросов (прежде всего потому, что разделены процессы написания кода и отладки), но возможности COM Add-Ins гораздо шире — это могут быть полноценные приложения с развитым пользовательским интерфейсом, с применением баз данных и всей функциональности .NET Framework. COM Add-Ins могут подключаться не только к среде VS.NET IDE, но и к Macro IDE. Механизм их создания фактически тот же самый, что использовался в VS 6.0, VB 6.0, VBA 6.0 и Microsoft Office, на базе подключения программного интерфейса IDTExtensibility2. Эти COM-компоненты можно писать, вообще говоря, на любом языке, поддерживающем COM, но специальные средства разработки COM Add-Ins в VS.NET позволяют работать только с VB.NET и C#.
Для создания COM Add-Ins в VS.NET нужно запустить мастер Add-Ins Project Wizard, который находится в папке Other Projects|Extensibility Projects диалогового окна New Project. Собственно, в этой папке два мастера — для создания расширения специально для VS.NET и совместное (Shared) дополнение, которое можно подключать к различным приложениям (в том числе Microsoft Office). Подробнее тему разработки COM Add-Ins в среде VS.NET мы рассмотрим в одной из последующих публикаций.
Листинг 1. Два макроса из состава проекта Samples
Imports EnvDTE Public Module VSEditor Sub NewCommentLine() ' вставляет в окно текущего документа ' строку, которую помечает ' как "комментарий" Dim ts As TextSelection = _ DTE.ActiveWindow.Selection ts.NewLine() ' определяет знак "комментария" для ' текущего языка программирования ts.Insert _ (Utilities.LineOrientedCommentStart()) ts.Insert(" ") End Sub Sub InsertTimeDate() ' вставляет в окно текущего документа ' значение текущей даты и времени Dim objTextSelection As TextSelection objTextSelection = _ CType(DTE.ActiveDocument.Selection(), _ EnvDTE.TextSelection) objTextSelection.Text = _ System.DateTime.Now.ToLongDateString() _ + " " + _ System.DateTime.Now.ToLongTimeString() End Sub End Module |