Чтение онлайн

ЖАНРЫ

Интернет-журнал "Домашняя лаборатория", 2007 №6
Шрифт:

Далее дается реализация двух экспортируемых из dll функций — DllGetClassObject и DllCanUnioadNow. Используя первую, менеджер управления сервисом (из СОМ) сможет активизировать фабрику класса запрашиваемого кокласса и получить указатель на интерфейс ICiassFactory соответствующей фабрики класса. Вторая функция используется менеджером на этапе принятия решения об удалении сервера из памяти.

Рассмотрим подробнее реализацию функции DllGetClassObject.

Эта функция получает в качестве аргументов ссылку на GUID нужного кокласса,

ссылку на желаемый интерфейс фабрики класса этого кокласса (обычно IID_IClassFactory) и в качестве выходного параметра возвращает указатель на запрашиваемый интерфейс. Возвращаемое функцией значение типа HRESULT говорит об успехе или неудаче операции. В последнем случае можно выяснить причину неудачи. Дня проверки успешности операции можно использовать определенные в СОМ макроопределения SUCCEEDED и FAILED, анализирующие старший бит возвращенного значения типа HRESULT.

Реализация функции DllCanUnioadNow тривиальна.

Обычно dll Сервер Экспортирует еще две функции: DllRegisterServer и DllUnregisterServer. Эти функиции должны обеспечить саморегистрацию сервера в реестре. В данном курсе этот вопрос не рассматривается, и регистрация разрабатываемого сервера будет проведена вручную с помощью редактора реестра.

Далее надо включить в проект стандартный DEF-файл PubInProcServer.def, который перечисляет экспортируемые функции:

LIBRARY "PUBINPROCSERVER"

EXPORTS

DllGetClassObject @1 PRIVATE

DllCanUnloadNow @2 PRIVATE

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

Регистрация сервера в реестре

Теперь сервер готов, но для его использования необходимо внести некоторые данные в реестр системы. Сделаем это, используя редактор реестра — regedit.ехе. Для внесения минимальной информации о сервере внесем в реестр следующие данные:

CLSID и соответствующие ProgID и путь к серверу

Программный идентификатор (ProgID) используется некоторыми программами как некоторая замена CLSID (требуется только локальная уникальность). Формат для ProgID

имя_сервера. имя_кокласса. Для CoBook это PuInProcServer.CoBook.

Под ключом HKEY_CLASSES_ROOT нужно найти ключ CLSID и под ним создать раздел {49F00760-7238-11d5-98C7-000001223694}. Это CLSID для кокласса CoBook. Для задания соответствующего ProgID следует для данного раздела создать подраздел с именем ProgID и в качестве значения для параметра по умолчанию взять PubInProcServer.CoBook.

Аналогично, под ключом HKEY_CLASSES_ROOT CLSID нужно еще создать раздел {49F00761-7238-11d5-98C7-000001223694}. Это CLSID ДЛЯ кокласса CoJournal.

Для задания соответствующего ProgID следует для данного раздела создать подраздел с именем ProgID и в качестве значения для параметра по умолчанию взять PubInProcServer.CoJournal.

Для задания пути к серверу (один сервер для двух коклассов), надо под ключом

НКЕY_CLASSЕS_ROOT CLSID {49F00760-7238-11d5-98С7-000001223694} создать раздел InProcServer32 и в качестве параметра по умолчанию задать полный путь к dll серверу.

Это же повторяется для CLSID кокласса CoJournal.

ProgID и соответствующий CLSID

Под ключом НКЕY_CLASSЕS_ROOT надо создать разделы PubInProcServer.CoBook и PubInProcServer.CoJournal. Для каждого из построенных разделов создать подразделы CLSID, где в качестве значения параметра по умолчанию задаются CLSID соответствующих коклассов.

Клиент

Теперь можно реализовать клиента для сервера PubInProcServer. Для этого можно в Visual C++ создать проект консольного приложения PubClient, куда перенести файлы iid.h, iid.cpp и все файлы с описаниями интерфейсов. Тем самым, клиент должен знать все GUID используемых коклассов и их интерфейсов (не обязательно всех в данном классе, но всех, используемых данным клиентом).

Сам клиент реализован в файле PubClient.cpp

// PubClient.cpp — клиент для сервера PubinProcServer

#include "IBook.h"

#include "IJournal.h"

#include "iid.h"

#include <iostream.h>

define MAX_ID 100 // максимальное число публикаций

int main

{

CoInitialize(NULL); // инициализация COM

IClassFactory* pBF = NULL;

IClassFactory* pJF = NULL;

IBook* pIBook = NULL;

IJournal* pIJournal = NULL;

BSTR bstr;

char* pszText;

HRESULT hr;

int nNewID = 0;

IPub* alPub[MAX_ID]; // массив указателей на публикации

bstr = SysAllocString(L"");

// Активация фабрики класса CoBookFactory и получение указателя на интерфейс IClassFactory этой фабрики (pBF)

hr = CoGetClassObject(CLSID_CoBook, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void**)&pBF);

if(FAILED(hr)) // в случае неудачи — выход

return 0;

// Активация фабрики класса CoJournaiFactory и получение указателя на интерфейс IClassFactory этой фабрики (pJF)

hr = CoGetClassObject(CLSID_CoJournal, CLSCTX_INPROC_SERVER,

NULL, IID_IClassFactory, (void**)&pJF);

if(FAILED(hr)) // в случае неудачи — выход

return 0;

// Активация нового экземпляра кокласса CoBook

hr = pBF —> CreateInstance(NULL, IID_IBook, (void**)SpIBook);

// В случае успеха — ввод данных

Поделиться с друзьями: