Версия для печати


Выполнение некоторых действий до и после компиляции проекта
http://www.delphikingdom.com/asp/viewitem.asp?catalogID=1421

Cepгей Poщин
дата публикации 14-02-2010 13:02

Выполнение некоторых действий до и после компиляции проекта

Позвольте представить небольшой эксперт, который добавляет в главное меню IDE Delphi пункт Run/Полная сборка и запуск. Как следует из названия, он выполняет полную перекомпиляцию проекта (команда Project/Build) и запуск приложения (Run/Run). Кроме того он позволяет выполнить некоторые действия перед и после команды Build.

Этот эксперт создавался для Delphi 5, с использованием кода из пакета Jedi Code Format, поэтому встречаются комментарии на английском языке и Warning`и.

В тексте запускающей команды можно использовать макросы, которые при выполнении будут заменены на соответствующий текст:

$PROJECT — полное имя файла проекта

$EXENAME — полное имя откомпилированного файла (exe, dll, ocx)

$HOSTNAME — полное имя запускающего приложения (Run/Parameters/Host Application)

$PARAMS — параметры запускающего приложения (Run/Parameters/Parameters)

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

Инсталляция

В прилагаемом архиве содержаться пакеты для Delphi 5 (ExecutePlug5.dpk), Delphi 6, 7 (ExecutePlug7.dpk), Delphi 2005-2010 (ExecutePlug12.dpk). Для того, чтобы внедрить предлагаемый эксперт в среду Delphi, откройте файл ExecutePlugNN.dpk, затем:

Для Delphi 2005 и старше, откройте окно Project Manager (Ctrl+Alt+F11), по правому клику на пункте ExecutePlug12.bpl выберите пункт контекстного меню install.

Для младших версий, в окошке проекта нажмите кнопку install.

Как это работает

Как и в любом пакете, определена процедура Register (см. модуль UnitRegister.pas), внутри которой должна осуществляться регистрация любых данных в среде разработки Delphi. Эта процедура вызывается при запуске среды, инсталляции пакета и при перекомпиляции инсталлированного пакета. Внутри этой процедуры следовало бы создать пункт меню, однако, в момент её вызова, вероятно, графический интерфейс оказывается еще не до конца проинициализированным, поэтому могут возникнуть ошибки (по крайней мере, в ранних версиях). По этому «перешагиваем грабли» и немного ждём, пока меню IDE будет полностью сформировано. Для этого выполняем добавление своего пункта меню (процедура AddMenuItems) используя таймер.

Удаление пунктов меню выполняет процедура RemoveMenuItems вызываемая в разделе finalization.

Для осуществления доступа к IDE используется глобальная переменная BorlandIDEServices из стандартной библиотеки ToolsAPI и множество интерфейсов. Получить нужный интерфейс можно несколькими способами:

Var 
  Переменная: Тип; 
  Результат: HResult; 
  Результат := BorlandIDEServices.QueryInterface({Тип}, {Переменная}); 
  Переменная := BorlandIDEServices as {Тип}; 
  Переменная := Тип(BorlandIDEServices);

В первом случае Вы можете самостоятельно выяснить был ли получен запрашиваемый интерфейс, в остальных будет сформировано исключение, если интерфейс не может быть получен. Чтобы получить доступ к главному меню воспользуемся интерфейсом INTAServices.

function GetToolsMenu(MenuName: string): TMenuItem; 
var 
  lciMenuServices: INTAServices40; 
  lcMainMenu: TMenu; 
begin{ запрашиваем необходимый интерфейс } 
  BorlandIDEServices.QueryInterface(INTAServices40, lciMenuServices); 
  … 
  { текущее главное меню } 
  lcMainMenu := lciMenuServices.MainMenu; 
  { находим пункт меню по заголовку } 
  Result := lcMainMenu.Items.Find(MenuName); 
end;

Обратите внимание, что по мере появления новых версий Delphi появляются и новые методы в наследниках интерфейса, в результате появляется довольно длинная цепочка наследований напр.:

IUnknown > INTAServices40 > INTAServices70 > INTAServices90 > INTAServices

Можно всегда использовать название интерфейса без номера, но тогда существует вероятность, что вы воспользуетесь методом, который не поддерживается в более ранних версиях.

Получив главное меню, искать существующие пункты и добавлять свои можно, как в обычной программе. Чтобы создать новый пункт меню сначала создаём действие TAction и добавляеем в общий список действий Delphi (INTAServices.ActionList), затем это действие привязываем к новому пункту меню.

Не буду останавливаться на создании формы.

Отображение формы, выполнение нужных команд и полная сборка проекта выполняется в методе TCepIdeMain.DoSpecBuild (см. модуль UnitMain).

Для выполнения компиляции необходимо получить доступ к активному проекту (см. функцию GetCurrentProject). Здесь, воспользовавшись интерфейсом IOTAModuleServices, получаем список модулей, из него выбираем тот, который является активным (если открыта группа проектов) модулем проекта. Найденный проект компилируем:

Proj.ProjectBuilder.BuildProject(cmOTABuild, false, true)

Для определения имени файла, который получится в результате компиляции, в версиях начиная 2005, можно использовать функцию IOTAProject.ProjectOptions.TargetName, а для более ранних версий это не такая уж и простая задача, которая реализована в модуле PCustFunc, автором которого является Юрий Спектор (Ins).

Для определения параметров запуска используется свойство IOTAProject.ProjectOptions.Values

Для записи информационных сообщений в журнал (окошко, где появляются сообщения об ошибках) используется метод IOTAMessageServices.lciMessages.AddToolMessage.

P.S. С выходом Delphi 2009 подобная функциональность появилась в стандартной IDE, однако надеюсь, статья будет кому-то полезна.

К материалу прилагаются файлы: