Реализация функции 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);
// В случае успеха — ввод данных
if (SUCCEEDED(hr))
{
SysReAllocString(&bstr, L" A.W.Troelsen");
pIBook — > SetAuthor(bstr);
SysReAllocString(&bstr, L" COM and ATL 3.0");
pIBook -> SetTitle(bstr);
pIBook —> SetYear(2000);
alPub [nNewID+ +] = pIBook;
}
// Активация нового экземпляра кокласса CoJournal
hr = pJF —> CreateInstance(NULL, IID_IJournal, (void**)SpIJournal);
// В случае успеха — ввод данных
if (SUCCEEDED(hr))
{
SysReAllocString(&bstr, L" The Journal of the Graph Theory");
pIJournal —> SetTitle(bstr);
pIJournal —> SetYear(2001);
pIJournal —> SetNumber(1);
aIPub[nNewID++] = pIJournal;
}
// Активация нового экземпляра кокласса CoJournal
hr = pJF->CreateInstance(NULL, IID_IJournal, (void**)SpIJournal);
// В случае успеха — ввод данных
if (SUCCEEDED(hr))
{
SysReAllocString(&bstr, L" SIGIR");
pIJournal —> SetTitle(bstr);
pIJournal —> SetYear (1999);
pIJournal —> SetNumber(12);
aIPub[nNewID++] = pIJournal;
}
// Удаление фабрик классов
pBF —> Release ();
pJF->Release ();
// Вывод информации о всех публикациях
if(nNewID)
for(int id = 0; id < nNewID; id++)
{
SysFreeString (bstr);
aIPub[id] — > GetInfo(&bstr);
pszText = (char*)malloc(2*SysStringLen(bstr));
wcstombs(pszText, bstr, 2*SysStringLen(bstr));