您的位置:首页 > 其它

用ATL为组件加入注册支持

2005-12-11 18:32 357 查看

用ATL为组件加入注册支持

hanlray@gmail.com

Revision: 1.0 Date: 2005/12/10如前文所述,在某些情况下我们需要一种不需要注册的COM组件,ATL完全支持这种情况,此时的COM组件除了在创建方法上较为特殊外(用ATL::CComObject的提供的静态方法CreateInstance来创建),和一个普通的C++类无异;另一方面,这样的组件也有重新被要求注册的可能性,如何为其加入这样的支持呢?
首先,应该为该组件分配一个GUID,并指定其所用的线程模型,progid等信息。用VC++的所谓属性化编程,应该类似下面这样:
[coclass, progid("MyCoClass.coclass.1"), vi_progid("MyCoClass.coclass"),
appobject, uuid("9E66A294-4365-11D2-A997-00C04FA37DDB")]
class CMyClass ...


第二步,为该组件类加入OBJECT_ENTRY_AUTO宏。CoCreateInstance函数的基本流程应该是这样的(对DLL形式的COM模块而言,以下同):根据CLSID在注册表中找到该组件所在的COM模块的路径,加载它,调用其导出的DllGetClassObject得到该组件的工厂对象,然后用该工厂对象创建一个组件实例。在ATL中这个导出的DllGetClassObject是由CAtlDllModuleT类来实现的,该类保存了一个所谓的Object Map,其中的每一项对应一个组件类,key为组件类的guid,value为组件类的相关信息,包括取得该组件类的工厂对象的函数指针,更新该组件类的注册信息的函数指针等。 当导出的DllGetClassObject被调用时,CAtlDllModuleT就在该Object Map中查找请求的组件类,调用相应的取得组件工厂对象的函数。OBJECT_ENTRY_AUTO宏就是把指定的组件类加到该Object Map中。
最后,创建一个Registrar Script资源,在组件类中加入DECLARE_REGISTRY_RESOURCEID宏。如第二步所述,CoCreateInstance要求注册表中必须要有该组件的注册信息,这一般是用regsvr32程序来写入的;为了支持regsvr32,DLL模块一般都会导出两个函数:DllRegisterServer/DllUnregisterServer,分别实现注册与反注册。CAtlDllModuleT类已有这两个函数的实现,不过它依赖组件类提供的注册信息。当导出的DllRegisterServer/DllUnregisterServer被调用时,CAtlDllModuleT就会针对Object Map中的每一项,调用相应的更新注册表的函数,其结果就把组件的注册信息写入了注册表。

OBJECT_ENTRY_AUTO宏会以组件类的静态函数UpdateRegistry作为更新该组件注册信息的函数,所以组件类还需要一个UpdateRegistry函数,这就是由DECLARE_REGISTRY_RESOURCEID宏来实现的,该宏的参数是一个resource ID,标识一个REGISTRY资源;该资源实际上是一个Registrar Script, 用BNF的语法描述了更新注册表的操作,下面是一个组件的例子:
HKCR
{
ATLAsync.ATLAsync.1 = s 'ATLAsync Class'
{
CLSID = s '{012F24D4-35B0-11D0-BF2D-0000E8D0D146}'
'Insertable'
}
ATLAsync.ATLAsync = s 'ATLAsync Class'
{
CLSID = s '{012F24D4-35B0-11D0-BF2D-0000E8D0D146}'
CurVer = s 'ATLAsync.ATLAsync.1'
}
NoRemove CLSID
{
ForceRemove {012F24D4-35B0-11D0-BF2D-0000E8D0D146} = s 'ATLAsync Class'
{
ProgID = s 'ATLAsync.ATLAsync.1'
VersionIndependentProgID = s 'ATLAsync.ATLAsync'
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
ForceRemove 'Control'
ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 1'
'MiscStatus' = s '0'
{
'1' = s '131473'
}
'TypeLib' = s '{012F24C1-35B0-11D0-BF2D-0000E8D0D146}'
'Version' = s '1.0'
}
}
}

具体更新注册表的操作会由Registry Script的引擎帮我们完成,我们所要做的只是按照规定的语法告诉其更新注册表的逻辑。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: