Добавить в цитаты Настройки чтения

Страница 182 из 372

Реализация функции 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));