码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-07-16 11:22:55      阅读:2539      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   使用   

1.      ATL注册组件

1.1     创建注册脚本

注册脚本通过操作 系统注册表完成Com服务的注册,通过数字形式而非代码API的形式完成,这种形式显得更加简单有效,因为它只需要几行数字代码就可以将一个Key添加到注册表中。

使用ATL向导时,会自动的生成一个后缀为.rgs的注册脚本文件,ATL在服务安装时,会自动的调用脚本文件,实现对注册表的修改,完成Com服务的注册。

 

符号释义

符号

解释

::=

相等

|

               

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 KeyDelete Key

 

? KeyName ::= ‘AlphaNumeric+‘

子键Name等于一个或多个任意的非空字符

 

?  registryexpression ::= [ForceRemove|NoRemove|val]

Add Key等于KeyNameForceRemoveNoRemoveval都是可选项

 

? 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 等于HKCRHKEY_CURRENT_USER等于HKCU等。

一个分析树可以一次添加一个或多个子键,这种方式通过避免一次只能添加一个子键的限制,显得很有效。

 

1.1.3       示例

【1】  【1】添加多个子键及键值 

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
HKCU
{
    ‘MyVeryOwnKey‘ ‘HowGoesIt?‘
    {
        ‘HasASubkey‘
        {
            ‘PrettyCool?‘ ‘55‘
            val ‘ANameValue‘ ‘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 ‘ATL Registrar Class‘
    {
        CLSID ‘{44EC053A-400F-11D0-9DCD-00A0C90391D3}‘
    }
    NoRemove CLSID
    {
        ForceRemove {44EC053A 400F 11D0 9DCD 00A0C90391D3} ‘ATL Registrar Class‘
        {
            ProgID ‘ATL.Registrar‘
            InprocServer32 ‘%MODULE%‘
            {
                val ThreadingModel ‘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服务的实际路径(dllexe的路径)

如:

‘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_RESOURCEDECLARE_REGISTRY_RESOURCEID宏。使用自定义的UpdateRegistry方法调用CAtlModule::UpdateRegistryFromResourceDCAtlModule::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表示模块路径,nIDszType表示资源的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

bubuko.com,布布扣
 bubuko.com,布布扣


【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‘ ‘My Software Test‘
    {
        NoRemove ‘VisualStudio‘
        {
            NoRemove ‘9.0‘
            {
                ForceRemove ‘CppClean.Connect‘
                {
                    val LoadBehavior    0
                    val CommandLineSafe 0
                    val FriendlyName    ‘CppClean AddIn‘
                }
            }
        }

        val DllPath ‘%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(NULLszModule, _MAX_PATH);   
    hr regOper.AddReplacement(OLESTR("Module"), T2OLE(szModule));
    if (SUCCEEDED(hr))
    {
        hr regOper.FileRegister(L"RegScript.rgs");
    }

    return 0  
}


【5】执行结果

bubuko.com,布布扣
bubuko.com,布布扣



【6】源码下载地址

RgsFile

ATL使用.rgs注册脚本文件操作注册表注册Com组件,布布扣,bubuko.com

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

标签:des   style   blog   http   color   使用   

原文地址:http://blog.csdn.net/aoshilang2249/article/details/37819209

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!