
- •Добавление к com-серверу поддержки событий
- •Создание модели взаимодействия приложения хоста с плагинами
- •Описание com-интерфейсов, связанных с поддержкой плагинов
- •Создание com-интерфейсов, связанных с поддержкой плагинов
- •Создание com-классов, связанных с поддержкой плагинов
- •Создание класса, отвечающего за взаимодействие с плагинами
- •Код класса Plugin.Cs
- •Внесение косметических изменений в серверную часть
- •Строим своё меню с плагинами и идентификаторами
- •Вносим изменения в главную форму сервера
- •Создание первого плагина
- •Импорт типов с сервера
- •Создание класса для хранения внутреннего представления точек
- •Создание форм редактирования данных о точках
- •Реализация форм редактирования данных о точках
- •Реализация класса первого плагина
- •Создание третьего плагина
- •Делаем наш плагин com-видимым
- •Создание главной формы плагина
- •Реализация класса третьего плагина
- •Создание инсталлятора для плагина
- •Создание второго плагина
- •Создание главной формы плагина
- •Создание библиотеки типов
- •Реализация формы второго плагина
- •Реализация класса второго плагина
- •Добавление метода GetComClassName
- •Data Execution Prevention и его отключение
- •Тестирование совместной работы клиента и плагинов
- •Исходный код
Добавление метода GetComClassName
Нам осталось выполнить только одно соглашение, чтобы наш плагин мог подключаться к серверу - мы должны реализовать функцию GetCOMClassName. Откройте Project Manager и через него откройте файл Plugin2.cpp. Допишем нужную функцию в самом конце этого файла.
// Функция, которая возвращает имя COM-класса плагина.
extern "C" char* __declspec(dllexport) __stdcall GetCOMClassName()
{
AnsiString s;
s = "Plugin2.ZigzagPlugin";
return s.c_str();
}
Extern "C" говорит компилятору, что данная функция должна быть компилирована в стиле чистого С. Нет, "Чистый С" - это не дешевое спиртосодержащее отбеливающее средство. В частности это значит, что к этой функции не будет применяться декорация имён. Подробнее про это есть на RSDN. __declspec(dllexport) говорит о том, что функция должна быть доступна извне библиотеки. __stdcall – задаёт соглашения вызова, об этом я уже говорил.
Фух, всё, кажется на этом с кодингом покончено. Сохраните все файлы и соберите проект. Если проект не собирается, то вспомните про то, что борланд билдер очень старый и может работать с глюками – попробуйте хотя бы перезапустить его. Если он так и не сбилдится – удачи в поиске ошибки. В случае, если вы так и не можете её найти, пишите на почту, если не буду сильно занят, то помогу.
Здесь надо признаться, что этот код является продуктом нескольких бессонных ночей, потому скорее всего где-то утекает память. Надеюсь, что вы будете более внимательны и без труда обнаружите такие места. Если она и утекает, то не очень быстро, в любом случае. Но я предупредил.
Data Execution Prevention и его отключение
Поддержку событий во втором плагине я добавил только в последней его редакции и с проблемой DEP (Data Execution Prevention) до этого не сталкивался. Теперь же, в тот момент, когда сервер генерировал событие создания новой точки и обработка доходила до перехвата события вторым плагином, сервер молча падал. Я попытался запустить сервер не из студии, а через исполняемый файл, и он мне выдал стандартное для Windows 7 окошко об ошибке, в котором было сказано, что моя программа убита по воле DEP-а. Видимо, старый борландский компилятор использует какие-то грязные трюки с памятью, которые в далёкие времена ещё прокатывали на старых системах. Достоверно известно, что такая проблема была у многих упаковщиков. Даже 1С Бухгалтерия, например, в своё время стала падать из-за DEP, да и не только она одна, много чего.
Возможно я попытаюсь разобраться с этой проблемой в будущем, попробую другие компиляторы, потыкаюсь в опции компиляции борланда, и так далее. Сейчас же я здесь объясню, как отключить DEP для нашего приложения. Решение я взял из статьи с поэтичным названием «To DEP or not to DEP». Она даст вам неплохое обзорное понимание проблемы предотвращения выполнения данных , если вы с ней не знакомы, при том условии, что вы понимаете английский. Кроме того, советую почитать вот здесь, уже на русском.
В первую очередь, нужно проверить, что система нам позволяет выключить DEP для отдельных приложений. Я покажу, как это сделать на Windows 7. Откройте свойства вашего компьютера. Можно, через пуск:
В открывшемся окне выбирайте пункт «Дополнительные параметры системы» в левой верхней менюшке.
В открывшемся диалоговом окне перейдите на вкладку «Дополнительно» и нажмите на кнопку «Параметры…» в групбоксе «Быстродействие».
В появившемся окне выбираем вкладку «Предотвращение выполнения данных» и включаем нижний вариант.
После этого обычно требуется перезагрузить систему.
Без выполнения предыдущего шага последующие действия результатов не принесут.
Дальнейшие действия имеют несколько вариантов. В том же окне можно нажать на кнопку «Добавить…» и добавить путь к нашему серверу. Кроме того, можно программно созадавать строковый параметр реестра по адресу:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
Имя параметра содержит путь к исполняемому файлу, а значение параметра равно DisableNXShowUI.
Кроме того, есть метод отключения контроля DEP за нашей программой на этапе её построения. Надо пометить её как NX-несовместимую, вызвав специальную утилиту. Лично я для себя избрал именно этот вариант. Откроем свойства проекта сервера.
Перейдём на вкладку «События построения» и добавим следующий код к командам после построения:
call "$(DevEnvDir)..\tools\vsvars32.bat"
editbin.exe /NXCOMPAT:NO "$(TargetPath)"
Сохраним свойства, нажав на Ctrl+S. Пересоберем проект сервера.
Всё, теперь наш второй плагин можно нормально тестировать.
Предупреждение: после этого всё равно возможны некоторые неувязки. Например, ваш сервер перестанет корректно работать в том случае, если вы запускаете его из студии. Однако, если сервер запускает приложение-клиент, то всё равботает нормально. Без поддержки событий второй плагин работает без проблем с DEP-ом, так что на стадии разработки поддержку событий можно временно отключить.