5.5 COM组件与注册表
我们知道,COM的重要性质之一是位置透明性。相对而言,以往在调用普通动态链接库中的输出函数时,必须要将此动态链接库放到应用程序的同级目录下(或系统可以找得到的目录下,如Windows目录、环境中已有的搜索路径等),或将动态库的位置信息硬编码到程序中的做法,其实都说明了普通动态库的位置不透明性。
当客户程序调用COM对象时,会更轻松一些,因为调用方不需要考虑COM组件所处的位置,不论它在哪个目录下,或是否在当前工作站上,一切都由系统提供的机制来保障对COM对象的定位,这就是位置无关性。
其实,COM位置无关性的实现机制并不深奥,它主要依赖于注册表,这也就是为什么一定要在使用之前对COM组件进行注册的原因。COM库在接到客户程序的请求后,会到注册表中检索COM对象的注册条目,并以此来定位COM对象。
对于我们刚刚编写的SimpleMath COM对象,如要使之能够成功地被COM库定位,则需要至少在注册表中写入如图5-4和5-5所示的信息。
观察这两个注册信息,可以发现它们之间是有联系的。现在在注册表的HKEY_ CLASSES_ROOT\键中增加了一个注册项{18034D20-B0C3-4135-9DCF-C2E12A58D330},这个GUID正是CLSID,代表COM类,对于我们的范例而言,就是CSimple_Math。

图5-4 组件的ProgID注册

图5-5 组件的CLSID信息注册
在这个注册项目下,有一个名为InProcServer32的字符串值,它代表容纳此COM 类的载体应当是一个动态链接库。这个字符串值的数据是“D:\Mytest\MySimpleMath.dll”,指明了组件所处的物理位置,这个信息对COM库查找和定位组件起到了决定性的作用。
下面还有一个名为ProgID的字符串值,其内容是MyCOM.SimpleMath.1。ProgID的出现主要是为了给长长的CLSID起一个“人性化”的名称,通常在客户程序中使用ProgID代替CLSID,有关信息将在5.6中详细论述。
另外,也可以使用ProgID在注册表中对COM对象进行标识,在图5-5中显示的信息就是所编写的SimpleMath组件ProgID的注册信息,其中一个名为CLSID字符串值的数据就是COM对象的CLSID值,所以,无论根据ProgID或CLSID,都可以定位到指定组件。
当然,COM组件不能天生就具备将注册信息写入到注册表中的功能,对进程内服务器而言,还必须实现两个名为DllRegisterServer和DllUnregisterServer的输出函数,来负责注册信息的写入和卸载。
HRESULT DllRegisterServer(void)
{
// 主要实现方法:
// 调用Windows API函数得到模块当前所在的物理位置,
// 调用Windows API操作注册表的函数创建图5-4、5-5中所示的注册项目
…(代码略)
}
HRESULT DllUnregisterServer(void)
{
// 主要实现方法
// 调用Windows API操作注册表的函数,在注册表中删除写入的信息。
(代码略)








