Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Что такое "технология COM" и как с ней бороться?


Служба Рассылок Subscribe.Ru проекта Citycat.Ru
М. Безверхов.
vasilisk@nm.ru
about@al.ru

Что такое "технология COM" и как с ней бороться?     №9

... и что именно COM хранит

В современном программировании системный реестр, начиная с какого-то уровня опытности программиста - знакомое понятие. Хоть раз и хоть где-то программист о нём слышал, а может быть - уже и лазал, да не просто из любопытства, но по делу.

Поэтому для большинства не будет новостью, что и COM хранит свою конфигурационную информацию там же. Вопрос в другом - что он там хранит?

Информация, которую использует система для обслуживания COM, многообразна. Она совершенно чётко и однозначно структурирована и эти правила не являются очень сложными. Другое дело, что в настоящий момент изложения большинство из понятий, которые можно было бы обнаружить в системном реестре относящимися к COM, ещё не введены нами в рассмотрение. Вследствие этого сейчас мы ограничимся только систематизацией этой информации и иллюстрацией, как же требуемая информация расположена. А недостающие знания о конкретных объектах в системном реестре мы будем вводить по мере продвижения вперёд.

Вообще говоря, я стал получать письма с одинаковым, по сути, вопросом - "Доколе же?". Я понимаю ваше нетерпение, уважаемые почитатели нашей рассылки, но наша аудитория неоднородна и вступительных экзаменов не имеет. Поэтому, дабы потом можно было говорить о чём-то более интересном понятно, поминутно не сбиваясь в определения и уточнения, я вначале неглубоко очерчиваю область рассмотрения в надежде, что не знающие каких-то понятий читатели будут иметь возможность увидеть свои пробелы и начнут отыскивать способы их ликвидации. Первые десять рассылок мною и предназначены только для этого, в 11-й рассылке вводится понятие "интерфейс", а фрагменты кода появляются с 12 - 13-й рассылок. Оставайтесь с нами! 

Итак, в системном реестре (иллюстрирующая наше объяснение программа вызывается на исполнение командой С:\WinNT\regedit.exe, если операционная система у вас расположена по адресу С:\WinNT) можно обнаружить несколько сущностей вида:

HKEY_CLASSES_ROOT

HKEY_CURRENT_USER

HKEY_LOCAL_MACHINE

и других аналогичных.

Они называются "части", являются корнями соответствующих отрастающих от них деревьев и являются предустановленными. Это означает - никакой "своей" части пользователь в реестре завести не может, не может также и переименовать или удалить существующую часть. Назначение частей предопределено, а их имена в написании часто сокращают. Программист COM должен знать, что аббревиатура HKCR обозначает часть HKEY_CLASSES_ROOT, а аббревиатура HKLM - HKEY_LOCAL_MACHINE. Думаю, что произвести  все другие возможные здесь аббревиатуры не составит никакого труда и самостоятельно.

Адресация в реестре производится аналогично указанию имени файла в файловой системе, но всегда - указанием полного пути. Например, строка :

HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\Identifier= "abcd"

ссылается на значение "abcd", располагающееся по приведённому пути.

Чем в данном случае является Identifier - разделом или параметром? В такой нотации это не видно да и установить невозможно - раздел, подобно параметру, может иметь значение, с ним ассоциированное. Но расположение этого значения - такой нотацией указывается точно.

К путанице такая небольшая неоднозначность не приводит, т.к. искать в системном реестре имя раздела или параметра, которым присвоено заданное значение может только человек. Программы-то, напротив, ищут значение в хорошо им известной структуре разделов и параметров, а они знают что должно чем являться. Нужно также еще сказать, что исторически устоялось, что часть идентификаторов разделов и параметров записывается прописными буквами, а часть - строчными. Но для функциональности это абсолютно несущественно, функции API, обслуживающие реестр, нечувствительны к регистру, в котором записаны идентификаторы.

Для "использования технологией COM" в системном реестре зарезервировано несколько подразделов. Главный, с точки зрения COM, подраздел это - HKEY_CLASSES_ROOT\CLSID. Если вы откроете его, то увидите, что весь он состоит из GUID, т.е. составляющие его разделы это - GUID. Каждый раздел обозначенный GUID содержит в себе информацию, относящуюся к одному COM-объекту, т.к. GUID и есть "официальное имя объекта". Посмотрим, что это за информация, которая собрана под именем GUID.

На моей машине первым по порядку следования (а порядок следования разделов и параметров в окне редактора реестра - по алфавиту) находится такой раздел:

HKEY_CLASSES_ROOT\CLSID\{00000010-0000-0010-8000-00AA006D2EA4},

которому присвоено значение DAO.DBEngine.35, т.е.

HKCR\CLSID\{00000010-0000-0010-8000-00AA006D2EA4} = DAO.DBEngine.35

Это - объект системы DAO доступа к данным машины Microsoft Jet Database Engine, версии 3.5. Его "идентификатор навсегда" на всех машинах установлен разработчиком этого объекта - 00000010-0000-0010-8000-00AA006D2EA4. А вот то, что это объект DAO я просто как-то  догадался… :)

Посмотрим также, что скрывается в разделе обозначенном этим GUID. Там располагаются еще два раздела:

HKCR\CLSID\{00000010-0000-0010-8000-00AA006D2EA4}\ProgID

HKCR\CLSID\{00000010-0000-0010-8000-00AA006D2EA4}\InprocServer32

Раздел ProgID пока лежит в стороне от нашего изложения, а вот раздел InprocServer32 очень любопытен, потому, что его значением (параметр Default) является строка:

C:\Program Files\Common Files\Microsoft Shared\DAO\DAO350.DLL

которая есть не что иное, как ссылка на исполняемый модуль, в котором обитает означенный COM-объект. Иными словами, если мы знаем GUID именующий требуемый нам объект, то нам достаточно посмотреть в системном реестре раздел:

HKCR\CLSID\<наш GUID>\InprocServer32,

прочитать присвоенное ему значение и выяснить, какой исполняемый модуль необходимо загрузить. Если такого GUID не обнаружится, то это означает, что такой COM-объект данной системе неизвестен. В самом начале нашего философского рассуждения о механизме разыскания объектов мы об этом говорили - система должна помнить имена статических типов COM-объектов и ссылки на исполняемые модули в которых объекты обитают. Теперь вы видите, каким образом система это делает "на самом деле". Терминологически такой модуль, реализующий COM-объекты называется "COM-сервер".

Рассмотрите еще несколько любых разделов - везде значением параметра InprocServer32 является строка с указанием имени DLL. Но ведь ранее говорилось, что COM-объект может жить и внутри EXE-модуля? И это тоже наблюдается - внутри некоторых GUID-разделов можно не обнаружить раздела InprocServer32, но обнаруживается раздел с именем LocalServer32. Например, на моей машине таковой первым нашелся у GUID 00020800-0000-0000-C000-000000000046:

HKCR\CLSID\{00020800-0000-0000-C000-000000000046}\LocalServer32

А его значением оказалась ссылка на EXE-модуль:

D:\Office\GRAPH9.EXE /automation

который, очевидно, должна запустить система когда от нее клиент потребует предоставить ссылку на объект 00020800-0000-0000-C000-000000000046

Нет ничего странного в том, что разделы, описывающие DLL и EXE-серверы называются по разному. Ведь и модули этих типов на исполнение загружаются тоже совершенно различно, а система должна возможность различать что есть что.

Кроме того, в разделе LocalServer32 обнаруживается еще и параметр ThreadingModel, значением которого является слово Apartment. Этот параметр описывает потоковую модель в которой может работать компонент (и подробное рассмотрение его случится в нашей же рассылке, но - ещё нескоро). Смысл параметра - если компонент вызывается из программы, владеющей несколькими потоками, то как следует его вызывать, а точнее - что "умеет компонент" по управлению конкурентным исполнением внутри себя, а что должна делать вызывающая сторона.

Ну и в заключение сегодняшней рассылки - что такое раздел ProgID связанный со статическим типом? Это - "человеческое имя" данного статического типа. Хотя GUID совершенно однозначно идентифицирует статический тип в некоторых случаях бывает удобнее пользоваться всё-таки мнемонически значимым именем. Раздел ProgID и связывает это мнемоническое имя с GUID. Внешнее (в реестре), а не внутреннее (в COM-сервере) связывание в данном случае совершенно оправданно - если на данной конкретной машине и возникнет конфликт мнемонических имён (см. рассылку №7), то ведь мнемоническое имя можно легко и сменить, в то время, как GUID никогда и нигде сменить невозможно. 

В следующей рассылке мы закончим обзорное рассмотрение ресурсов, сформулированных в рассылках №№ 5 и 6 и начнём "серьёзное изучение COM".

 

 предыдущий выпуск

архив и оглавление

 следующий выпуск

 

Авторские права © 2001, М. Безверхов
Публикация требует разрешения автора.



http://subscribe.ru/
E-mail: ask@subscribe.ru

В избранное