developing.ru - клуб программистов Здесь может быть и ваша реклама.
developing.ru >технология COM >
Михаил Безверхов
aspid@developing.ru

... и что именно 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. Например, на моей машине таковой первым нашелся у GUID00020800-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-сервере) связывание в данном случае совершенно оправданно - если на данной конкретной машине и возникнет конфликт мнемонических имён (см. статью Именование потенциальных COM-объектов), то ведь мнемоническое имя можно легко и сменить, в то время, как GUID никогда и нигде сменить невозможно. 

В следующей статье мы закончим обзорное рассмотрение ресурсов, сформулированных в статьях С чего начинается COM? и Что почём в этом COM? и начнём "серьёзное изучение COM".

предыдущий выпускархив и оглавлениеследующий выпуск
Авторские права © 2001 - 2004, Михаил Безверхов
Публикация требует разрешения автора

разделы сайта

форум

технология COM

оптимизация сайтов


© 2000-2004 Клуб программистов developing.ru