1. ATL注册组件
1.1 创建注册脚本
注册脚本通过操作 系统注册表完成Com服务的注册,通过数字形式而非代码API的形式完成,这种形式显得更加简单有效,因为它只需要几行数字代码就可以将一个Key添加到注册表中。
使用ATL向导时,会自动的生成一个后缀为.rgs的注册脚本文件,ATL在服务安装时,会自动的调用脚本文件,实现对注册表的修改,完成Com服务的注册。
1.1.1 基本术语
符号释义
符号 | 解释 |
::= | 相等 |
| | 或 |
X+ | 一个或多个Xs |
[X] | X是可选的 |
字符串字面值:
字符串字面值 | 行为 |
ForceRemove | 如果存在则删除,再重新建立 |
NoRemove | 反注册时,不删除 |
val | 用于指定一个键的值 |
Delete | 在注册时,删除Key |
s | 类型为REG_SZ |
d | 类型为REG_DWORD |
m | 类型为REG_MULTI_SZ |
b | 类型为REG_BINARY |
示例:
Ø val'testhex' = d
键testhex的值类型为REG_DWORD, 值为&H55
Ø val'testmulti' = m
键testmulti的值类型为REG_MULTI_SZ, 值为String 1 String2
Ø registryexpression ::= AddKey | DeleteKey
注册表达式等于Add Key 或Delete Key
Ø KeyName ::= 'AlphaNumeric+'
子键Name等于一个或多个任意的非空字符
Ø registryexpression ::= [ForceRemove|NoRemove|val]
Add Key等于KeyName,ForceRemove、NoRemove、val都是可选项
Ø AlphaNumeric ::=any character not NULL, that is, ASCII 0
AlphaNumeric为任意的非空字符
1.1.2 分析树
在注册脚本文件中,你可以使用一个或多个分析树对注册表进行操作,其树型结构类似文件夹的目录与文件结构,单个结构如下:
root key{registryexpression}+
详细介绍如下:
rootkey ::= HKEY_CLASSES_ROOT | HKEY_CURRENT_USER |
HKEY_LOCAL_MACHINE | HKEY_USERS |
HKEY_PERFORMANCE_DATA | HKEY_DYN_DATA |
HKEY_CURRENT_CONFIG | HKCR | HKCU |
HKLM | HKU | HKPD | HKDD | HKCC
registryexpression ::= AddKey | DeleteKey
AddKey ::=[ForceRemove | NoRemove | val]Key Name
[KeyValue][{< AddKey>}]
DeleteKey ::= Delete KeyName
KeyName ::='AlphaNumeric+'
AlphaNumeric ::=any character not NULL, i.e. ASCII 0
KeyValue ::== KeyType KeyName
KeyType ::=s | d
KeyValue ::='AlphaNumeric'
具体含义,基本术语已经详细介绍了,其中HKEY_CLASSES_ROOT 等于HKCR,HKEY_CURRENT_USER等于HKCU等。
一个分析树可以一次添加一个或多个子键,这种方式通过避免一次只能添加一个子键的限制,显得很有效。
1.1.3 示例
【1】 【1】添加多个子键及键值
C++ Code
|
在主键HKCU下添加了默认值为'HowGoesIt?'的子键'MyVeryOwnKey',在该子键下添加'HasASubkey'子键,在'HasASubkey'子键下,添加了默认值为'55'的'PrettyCool?'子键和键值对为'WithANamedValue'的'ANameValue',类似文件夹与文件的层次关系,很简单
【2】 注册Com服务
C++ Code
|
这段理解很简单,在HKCR主键下添加了默认值为'ATL RegistrarClass'的ATL.Registrar子键,在ATL.Registrar子键下添加了默认值为{44EC053A-400F-11D0-9DCD-00A0C90391D3}的CLSID子键。
在HKCR主键下添加了CLSID子键,设定属性为NoRemove,表示反注册时,不删除该子键,在该子键下添加默认值为'ATLRegistrarClass的{44EC053A-400F-11D0-9DCD-00A0C90391D3}子键,设定属性为ForceRemove,表示注册时,如果存在该子键,则首先将该子键下的所有的子键与键值都删除,再重新建立。在{44EC053A-400F-11D0-9DCD-00A0C90391D3}子键下添加了默认值'ATL.Registrar'的子键ProgID与默认值为'%MODULE%'的InprocServer32子键(%MODULE%会自动释义为模块的全路径),在InprocServer32子键下添加键值对'Apartment'的ThreadingModel。
注意一个注册脚本的大小为4K!!!
1.1.4 可替换参数
%MODULE% ——Com服务的实际路径(dll或exe的路径)
如:
'MySampleKey' =s
在调用注册脚本前,需要建立可替换参数MODULE的映射,调用AddReplacement添加映射,如下:
C++ Code
|
这样,在运行时,MODULE会自动释义为Com服务的全路径。
注意:
为了替换可替换参数的值,需要脚本中移除DECLARE_REGISTRY_RESOURCE 和DECLARE_REGISTRY_RESOURCEID宏。使用自定义的UpdateRegistry方法调用CAtlModule::UpdateRegistryFromResourceD或CAtlModule::UpdateRegistryFromResourceS,传入类型为_ATL_REGMAP_ENTRY结构体的数组(至少有一个元素设为{NULL,NULL},且为最后一个元素)否则调用UpdateRegistryFromResource将产生错误。
当创建的是可执行的exe服务时,使用可替换参数%MODULE%,运行时会自动的在映射的路径上添加引用,如果你不想要,可以使用%MODULE_RAW%替换%MODULE%;如果创建的是DLL,则不会添加引用。
1.2 调用注册脚本
使用API调用注册脚本很简单,这里简单介绍:
方法 | 详细解释 |
ResourceRegister | HRESULT ResourceRegister(LPCOLESTR resFileName ,UINT nID ,LPCOLESTR szType ); 注册脚本包含在资源文件中.resFileName表示模块路径,nID和szType表示资源的ID与类型。 |
ResourceUnregister | HRESULT ResourceUnregister(LPCOLESTR resFileName ,UINT nID ,LPCOLESTR szType ); |
ResourceRegisterSz | HRESULT ResourceRegisterSz(LPCOLESTR resFileName ,LPCOLESTR szID ,LPCOLESTR szType ); szID包含资源字符串的标识 |
ResourceUnregisterSz | HRESULT ResourceUnregisterSz(LPCOLESTR resFileName ,LPCOLESTR szID ,LPCOLESTR szType ); |
FileRegister | HRESULT FileRegister(LPCOLESTR fileName );注册脚本包含在文件中 |
FileUnregister | HRESULT FileUnregister(LPCOLESTR fileName ); |
StringRegister | HRESULT StringRegister(LPCOLESTR data ); 注册脚本包含在字符串中 |
StringUnregister | HRESULT StringUnregister(LPCOLESTR data ); |
1.3 完整测试用例
前面介绍的都是基于ATL向导生成的工程,来操作注册表,完成Com组件的注册,很简单,没有什么技术含量,实用性不强。那如果非ATL向导生成的工程也想使用rgs注册脚本文件进行注册表的操作可以吗?答案是肯定的!
本测试用例就是基于win32控制台应用程序,通过rgs注册脚本文件,操作注册表。
有以下几个步骤:
【1】项目属性要设置使用ATL
【2】添加rgs注册脚本文件,设置注册的内容
C++ Code
|
【3】编写操作rgs文件的代码
C++ Code
|
【4】执行代码
C++ Code
|
【5】执行结果
【6】源码下载地址
标签:rgs,hr,ATL,注册,注册表,NULL,子键,LPCOLESTR From: https://blog.51cto.com/u_13675550/7036701