При закрытии подписчики были переданы в рассылку "Мастерская программиста" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
Что такое "технология COM" и как с ней бороться? №25
Глупый пингвин робко прячет... сервер - смело достаёт!
Тема нашего сегодняшнего номера рассылки - информация, которую необходимо предоставить COM-серверу системе, чтобы система считала его "настоящим". Как упоминалось ранее, экспортируемая функция DllRegisterServer является тем самым входом, вызывая который можно заставить сервер зарегистрировать существенную для функционирования COM информацию в реестре. Но, что эта за информация, откуда она берется и каким образом она регистрируется?
Это - очень большая и самая, как я считаю, методически невнятная тема в спецификации COM. С одной стороны, в ней нет ничего "непроходимо сложного", напротив, эта тема - полностью лишь список соглашений о параметрах, их значениях и месте расположения в реестре. С другой - едва ли возможно как-то систематически изложить её до тех пор, пока мы не будем понимать смысла наличия соответствующих параметров и их влияния на явление COM в целом. С третьей - если мы хотим построить работающий пример, то обойти это затруднение никак не получается. Без регистрации сервера в реестре CoCreateInstance работать не будет.
Поэтому, видимо, так и придётся рассматривать эту тему "ломтями", соответственно месту, в котором мы находимся по порядку изложения. Итак... Ранее, в рассылке № 5 "С чего начинается COM" мы говорили, что система хранит информацию обо всяком, как мы теперь правильно скажем, статическом типе COM, а в рассылке № 9 "что именно COM хранит" назывались разделы и параметры системного реестра, в которых хранится эта информация. Но там мы только обозначили тему в объёме, достаточном для продолжения повествования, а сейчас мы можем вернуться к тому же, но с бóльшими подробностями.
Главным, с точки зрения разыскания сервера, ответственного за реализацию статического типа обозначенного указываемым клиентом CLSID, является раздел системного реестра HKEY_CLASSES_ROOT\CLSID, в котором имеются параметры под именами соответствующих CLSID, подпараметры которых описывают характеристики запуска соответствующего сервера. В рассылке №9 пример такого параметра был приведён, применительно к нашему нынешнему случаю он будет выглядеть так:
HKCR\CLSID\{CLSID нашего статического типа} = <"человеческое имя" типа>
и у этого параметра имеется, как минимум, вложенный параметр - InprocServer32, значением которого является спецификация полного пути, где располагается модуль сервера.
Поэтому minimum minimorum информации о статическом COM-типе, который нужно вписать в реестр, если клиент собирается "поднимать" объект только по имени его CLSID и только если объект реализуется inproc-сервером на данной же машине:
HKCR\CLSID\{CLSID нашего статического типа} = ""
HKCR\CLSID\{CLSID нашего статического типа}\InprocServer32 = <спецификация полного пути в файловой системе>
В принципе, этого достаточно, чтобы вызвав CoCreateInstance получить ссылку на запрашиваемый интерфейс объекта данного статического типа. (И в для написания примера, сопровождающего нашу рассылку - тоже достаточно). Но, в реальной жизни, так бывает не всегда... Мало кто желает иметь дело с GUID в его "натуральном выражении" - информативности у GUID нет никакой по определению самого же GUID (см рассылку №7 "Именование потенциальных COM-объектов"). Поэтому с объектом обычно (но обязательно этого не требуется, просто часть сопутствующих сервисов будет неработоспособна) связывается еще и "человеческое имя" - обозначение из нескольких символьных идентификаторов, разделённых точками, структура которого устанавливается следующей:
<название приложения>.<имя статического типа>.<версия>.<подверсия>...<...>
например: Word.Document.6
Структурированность имени позволяет выяснить отношения преемственности между серверами, компонентами и версиями - другой, тоже возможный здесь же, параметр реестра VersionIndependentProgID имеет своим значением только <название приложения>.<имя статического типа>, что позволяет в случае необходимости разыскивать либо "общеизвестную" версию компонента, либо - точно заданную. Впрочем, если клиент знает точный GUID компонента, этой проблемы не существует вовсе - он просто адресует GUID, а GUID всех других версий этого же компонента должны быть уже другими.
Нужно специально отметить: и название приложения и имя статического типа - имена нарицательные. Они не связаны ни с именем файла сервера, ни с именем класса компонента. Например, все версии Microsoft Word имеют одно нарицательное имя Word.
Поэтому более полная информация о статическом типе будет содержать ещё и параметр ProgID:
HKCR\CLSID\{CLSID нашего статического типа}\ProgID = <"человеческое имя">
а уж совсем продвинутая еще и параметр:
HKCR\CLSID\{CLSID нашего статического типа}\VersionIndependentProgID = <"короткое имя">
К последовательности идентификаторов, являющихся значением ProgID и VersionIndependentProgID применимы следующие правила:
Они в совокупности не должны быть длиннее GUID, т.е. 39 символов;
Они не могут содержать знаков пунктуации, в том числе - знаков подчёркивания, исключение - только разделяющие точки;
Последовательность не должна начинаться с цифры.
Но перечисленное - еще не всё. Описанный набор параметров задаёт связь "CLSID - ProgID", а существует и "зеркальный набор параметров реестра", который задаёт связь "ProgID - CLSID". Его можно отыскать прямо в разделе реестра HKEY_CLASSES_ROOT:
HKCR\<название приложения>.<имя статического типа> = <строковое описание>
HKCR\<название приложения>.<имя статического типа>.<версия> = <строковое описание>
Внутри этих параметров определен вложенный параметр CLSID, значением которого является GUID из раздела HKEY_CLASSES_ROOT\CLSID, вот так:
HKCR\<название приложения>.<имя статического типа> = <строковое описание>
HKCR\<название приложения>.<имя статического типа>\{CLSID нашего статического типа} = <GUID>
HKCR\<название приложения>.<имя статического типа>.<версия> = <строковое описание>
HKCR\<название приложения>.<имя статического типа>.<версия>\{CLSID нашего статического типа} = <GUID>
Здесь <строковое описание> - произвольная и необязательная строка символов, которая может содержать всё, что угодно. Она используется браузерами реестра для того, чтобы выдать откомментированное описание компонента, но для функционирования "собственно COM" никакого значения не имеет..
Существует практическое правило, по которому инсталлятор самой первой версии продукта записывает данные параметры в реестр следующим образом:
HKCR\<мой продукт>.<мой тип>.1 = "первая версия продукта"
HKCR\<мой продукт>.<мой тип>.1\{CLSID данного типа в версии 1} = <GUID>
HKCR\<мой продукт>.<мой тип> = "последняя известная системе версия продукта"
HKCR\<мой продукт>.<мой тип>\{CLSID данного типа в версии 1} = <GUID>
Если поверх первой версии данного программного продукта будет устанавливаться вторая его версия, то её инсталлятор запишет в реестр следующие строки:
HKCR\<мой продукт>.<мой тип>.2 = "вторая версия продукта"
HKCR\<мой продукт>.<мой тип>.2\{CLSID данного типа в версии 2} = <GUID>
HKCR\<мой продукт>.<мой тип> = "последняя известная системе версия продукта"
HKCR\<мой продукт>.<мой тип>\{CLSID данного типа в версии 2} = <GUID>
т.е. он перезапишет значения параметра HKCR\<мой продукт>.<мой тип> В результате, после работы обоих инсталляторов в реестре окажется совокупность записей:
HKCR\<мой продукт>.<мой тип>.1 = "первая версия продукта"
HKCR\<мой продукт>.<мой тип>.1\{CLSID данного типа в версии 1} = <GUID>
HKCR\<мой продукт>.<мой тип>.2 = "вторая версия продукта"
HKCR\<мой продукт>.<мой тип>.2\{CLSID данного типа в версии 2} = <GUID>
HKCR\<мой продукт>.<мой тип> = "последняя известная системе версия продукта"
HKCR\<мой продукт>.<мой тип>\{CLSID данного типа в версии 2} = <GUID>
Такое правило позволяет хранить в системе одновременно все версии компонентов данного статического типа и реализующих их серверов без взаимной интерференции, если, конечно, инсталлятор последующих версий намеренно не удаляет все предыдущие. Но, конечно, никто и не обязывает инсталлятор делать VersionIndependentProgID обязательно последней устанавливающейся версией. Например, если вы выпускаете beta-release вашего продукта, то более безопасным будет считать independent-версией как раз не последнюю, а предыдущую... Поскольку все GUID - разные, подобная проблема не возникает в разделе HKCR\CLSID, туда инсталлятор просто должен вписывать "свои" параметры, корректируя только VersionIndependentProgID по необходимости, и не трогая никаких других.
Вот, собственно и весь фрагмент регистрационной информации, которая требуется нам на настоящем этапе нашего повествования. Безусловно, это - не всё, кое-что опущено, но когда-нибудь мы доберёмся до такого выпуска рассылки в которой мы сможем все наши предыдущие "слои" информации о системном реестре обобщить и свести все вместе. В следующей рассылке - каким образом и при помощи каких средств такую регистрацию выполнить.
И напоследок - зачем всё это? Я получаю время от времени вопросы "зачем нам это надо, если...". Уважаемые читатели нашей рассылки! Я понимаю, что для того, чтобы снять квартиру, совсем не обязательно быть специалистом в домостроении и архитектуре... Но, если вы претендуете на звание архитектора, а не маклера-риэлтора, то, наверное, надо иметь представление о том, что есть "кирпичная кладка"? И что "из кирпича, в принципе, можно построить"? Вас никто не заставляет становиться каменщиком, но, видимо, вам всё-таки надо знать, сколько и какого труда стоит действительно построить то или иное архитектурное решение?
Я не пытаюсь этим навязать отказ от сервисных средств (какой вывод сделали некоторые читатели из наших предыдущих рассылок), которые должно использовать в процессе разработки. Я просто утверждаю - чтобы не стать их заложником нужно представлять себе объём действий, которые выполняют сервисные средства для вас и нужно представлять себе эти действия...
Авторские права © 2001, М. Безверхов
Публикация требует разрешения автора.
http://subscribe.ru/
E-mail: ask@subscribe.ru | Отписаться | Relayed by Corbina
Рейтингуется SpyLog |
В избранное | ||