ATL使用.rgs注册脚本文件操作注册表注册Com组件

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 ‘&H55‘

testhex的值类型为REG_DWORD,
值为&H55

? val‘testmulti‘
= m ‘String 1\0String2\0‘

键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


1

2

3

4

5

6

7

8

9

10

11


HKCU

{

‘MyVeryOwnKey‘ = s ‘HowGoesIt?‘

{

‘HasASubkey‘

{

‘PrettyCool?‘ = d ‘55‘

val ‘ANameValue‘ = s ‘WithANamedValue‘

}

}

}

在主键HKCU下添加了默认值为‘HowGoesIt?‘的子键‘MyVeryOwnKey‘,在该子键下添加‘HasASubkey‘子键,在‘HasASubkey‘子键下,添加了默认值为‘55‘的‘PrettyCool?‘子键和键值对为‘WithANamedValue‘的‘ANameValue‘,类似文件夹与文件的层次关系,很简单

【2】 注册Com服务

C++ Code


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18


HKCR

{

ATL.Registrar = s ‘ATL Registrar Class‘

{

CLSID = s ‘{44EC053A-400F-11D0-9DCD-00A0C90391D3}‘

}

NoRemove CLSID

{

ForceRemove {44EC053A - 400F - 11D0 - 9DCD - 00A0C90391D3} = s ‘ATL Registrar Class‘

{

ProgID = s ‘ATL.Registrar‘

InprocServer32 = s ‘%MODULE%‘

{

val ThreadingModel = s ‘Apartment‘

}

}

}

}

这段理解很简单,在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%,1‘

在调用注册脚本前,需要建立可替换参数MODULE的映射,调用AddReplacement添加映射,如下:

C++ Code


1

2

3


TCHAR szModule[_MAX_PATH];

::GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szModule, _MAX_PATH);

p->AddReplacement(OLESTR("Module"), T2OLE(szModule)); 

这样,在运行时,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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20


HKEY_CURRENT_USER

{

NoRemove ‘MySOFTWARE‘ = s ‘My Software Test‘

{

NoRemove ‘VisualStudio‘

{

NoRemove ‘9.0‘

{

ForceRemove ‘CppClean.Connect‘

{

val LoadBehavior    = d 0

val CommandLineSafe = d 0

val FriendlyName    = s ‘CppClean AddIn‘

}

}

}

val DllPath = s ‘%Module%‘

}

}

【3】编写操作rgs文件的代码

C++ Code


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87


#ifndef _AFXSTD_091159A6_4CF3_4FD0_87B6_8411D7A2F123_INCLUDE_H_

#define _AFXSTD_091159A6_4CF3_4FD0_87B6_8411D7A2F123_INCLUDE_H_

#if _MSC_VER > 1000

#pragma once

#endif

#include "afxwin.h"

#include "atlbase.h"

#include "statreg.h"

#define  ATL_NO_ASSERT_ON_DESTROY_NONEXISTENT_WINDOW

#define  BREAK_ON_FAIL(value)            if (FAILED(value)){break;}

#define  BREAK_ON_NULL(value, newHr)     if (NULL == value){hr = newHr; break;}

class CRegOper

{

public:

CRegOper(HRESULT *pHr)

{

::CoInitialize(NULL);

HRESULT hr = CoCreateInstance(CLSID_Registrar,

NULL,

CLSCTX_INPROC_SERVER,

IID_IRegistrar,

(void**)&m_pRegistrar);

if (NULL != pHr)

{

*pHr = hr;

}

}

virtual ~CRegOper()

{

m_pRegistrar = NULL;

::CoUninitialize();

}

public:

//添加可替换参数映射

HRESULT AddReplacement(LPCOLESTR lpszKey,  LPCOLESTR lpszItem)

{

HRESULT hr = S_OK;

do

{

BREAK_ON_NULL(m_pRegistrar, E_POINTER);

hr = m_pRegistrar->AddReplacement(lpszKey, lpszItem);

} while (false);

return(hr);

}

//rgs文件注册,传入rgs文件的全路径

HRESULT FileRegister(PCWSTR pRegFilePath)

{

HRESULT hr = S_OK;

do

{

BREAK_ON_NULL(m_pRegistrar, E_POINTER);

hr = m_pRegistrar->FileRegister(pRegFilePath);

} while (false);

return(hr);

}

//rgs文件反注册,传入rgs文件的全路径

HRESULT FileUnregister(PCWSTR pRegFilePath)

{

HRESULT hr = S_OK;

do

{

BREAK_ON_NULL(m_pRegistrar, E_POINTER);

hr = m_pRegistrar->FileUnregister(pRegFilePath);

} while (false);

return(hr);

}

private:

CComPtr m_pRegistrar;

};

#endif // !_AFXSTD_091159A6_4CF3_4FD0_87B6_8411D7A2F123_INCLUDE_H_

【4】执行代码

C++ Code


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27


#include "stdafx.h"

#include "RegOper.h"

int _tmain(int argc, _TCHAR* argv[])

{

HRESULT   hr  = S_OK;

CRegOper  regOper(&hr);

if (FAILED(hr))

{

return(1);

}

TCHAR szModule[_MAX_PATH] = {0};

USES_CONVERSION;

GetModuleFileName(NULL, szModule, _MAX_PATH);

hr = regOper.AddReplacement(OLESTR("Module"), T2OLE(szModule));

if (SUCCEEDED(hr))

{

hr = regOper.FileRegister(L"RegScript.rgs");

}

return 0;

}

【5】执行结果

【6】源码下载地址

RgsFile

ATL使用.rgs注册脚本文件操作注册表注册Com组件

时间: 2024-10-25 04:28:07

ATL使用.rgs注册脚本文件操作注册表注册Com组件的相关文章

注册(文件操作)

infoFile = 'E:/userinfo.txt' # \\或者/ i = 0 for i in range(3): flag = True username = input('please inupt username:').strip() passwd = input('please inupt passwd:') confirm_passwd = input('please inupt confirm_passwd:') with open(infoFile, 'r') as f:

使用ClientScriptManager向客户端注册脚本

ClientScriptManager在非异步(就是说非AJAX)环境下使用的.如果要在异步环境下注册脚本应该使用ScriptManager的静态方法来注册(ScriptManager兼容异步于非异步环境下注册脚本).ClientScriptManager中注册脚本的方法在ScriptManager中都有一一对应的方法,但是有一些区别,ScriptManager中的方法多了一个参数(多了第一个参数),而且使用ScriptManager来注册脚本不是绝对能注册成功的. .aspx文件代码 <%@ 

个人的后门程序开发(第一部分):文件操作和注册表管理

本来是想寒假时写的,结果一直懒得动手. 虽然手上有ghost源码,但是感觉功能不是我想要的,比如把精力费在学MFC写界面上不如改进下隐藏性. 基本的计划就是做一个后门程序,目的是用来进行权限维持的.目前来看是基于控制台的,而且要带有内核模块,应用层的主要问题就是没写过太大体量的程序导致搞起来很蛋疼,内核方面就是通用性坑爹, 蓝屏起来也要费时间. 第一部分就是封装的两个函数,文件操作和注册表管理.ghost是把这两个功能封装成两个类,我这里就直接用函数来实现了. VS2015编译通过 1 //文件

python 基础(文件操作,注册,以及函数)

1,文件操作 1,文件路径: 2,编码方式:utf-8, gbk.... 3,操作方式:只读,只写,追加,读写,写读 1,只读 :r   rb   不用编码,以什么形式存储就以什么形式读出来 f = open('  文件名',mode = 'r',encoding = 'utf-8') content = f.read() print(content) f.close()  必须存在 2,只写:w     没有此文件就会创建,先将源文件的内容全部清除,再写    wb不用编码 3,追加:a 4,

python-15-常用文件操作与注册登录练习

前言 1.常用的文件操作无非就是读或写,但python中没有提供文件修改的功能,是无法实现,但我们可以新增-删除源文件-更改新增文件为源文件名称. 2.使用文件的存储与读取方式来简单完成注册.登录功能,需求如下: 1.注册,设置的账号密码用文件存储: 2.登录,读取账号密码判断,错误三次机会并提醒: 一.新增-删除源文件-更改新增文件为源文件名称 1.文件内容如下,需要将“欣欣”修改为“小龙”. 2.运用os模块,删除源文件.更改新文件名称为源文件名称即可.(感觉就像修改文件一样) f = op

使用Js脚本 修改控制IE的注册表相关设置(activex等)

使用Js脚本 修改控制IE的注册表相关设置(activex等) 分类: PHP2012-12-05 18:51 2035人阅读 评论(2) 收藏 举报 脚本写法: <SCRIPT LANGUAGE="JavaScript"><!--var WshShell=new ActiveXObject("WScript.Shell"); //添加信任站点ipWshShell.RegWrite("HKCU\\Software\\Microsoft\\

linux的chkconfig服务注册(服务注册脚本说明)

linux上一些服务的重启以及随系统启动而启动,可以像windows那样注册为服务通过chkconfig 进行操作.在注册chkconfig时需要在linux的/etc/init.d/目录下有对应的启动脚本. 一.注册服务脚本说明 1./etc/init.d/目录下的脚本名称就是服务注册时使用的服务名. 2.在服务脚本中一般包括start/stop/restart/status/condrestart/reload几种操作 start:启动服务 stop:停止服务 status:查看服务状态 c

C# 注册自定义文件类型 实现自定义文件类型关联应用程序

在我们自己编写的应用中,经常会用自定义类型的文件来保存与应用相关的数据,比如.osf文件就是应用程序的项目文件.如果没有向Windows注册表注册该文件类型,那么.osf文件的图标将是windows的文件默认图标,并且你双击一个a.osf文件,也不会自动启动应用程序来加载a.osf文件.如何使.osf文件的图标变成我自己喜爱的图标.如何完成像点击.doc文件就自动打开word 程序的功能,下面将告诉你解决方案. 我们可以通过手动修改注册表来完成上述任务,更好的方式是,通过程序来实现.这样在安装应

注册DLL文件

一.注册DLL文件注册AutoItX3.dll 文件在XP X86和WIN7 X86系统中 只需要运行X:\autoit3\AutoItX\注册DLL.CMD 就可以将DLL文件注册到计算机中. WIN7 X64环境下需要将X:\autoit3\AutoItXAutoItX3_x64.dll和AutoItX3.dll 分别拷贝到C:\Windows\System32 和 C:\Windows\SysWOW64 下面进行注册. regsvr32 "C:\Windows\System32\AutoI