COM组件是跨语言的,组件被注册到注册表中,在加载时由加载函数在注册表中查找到对应模块的路径并进行相关加载。它的存储规则如下:

1. 在注册表的HKEY_CLASSES_ROOT中以模块名的方式保存着COM模块的GUID,比如HKEY_CLASSES_ROOT\ADODB.Error\CLSID键中保存着模块ADODB.Error的GUID为{00000541-0000-0010-8000-00AA006D2EA4}

2. 在HKEY_CLASSES_ROOT\CLSID中以GUID为项名保存着对应组件的详细信息,比如之前的{00000541-0000-0010-8000-00AA006D2EA4}这个GUID在注册表中的位置为HKEY_CLASSES_ROOT\CLSID\{00000541-0000-0010-8000-00AA006D2EA4}\InprocServer32\项的默认键中保存着模块所在路径为%CommonProgramFiles%\System\ado\msado15.dll

一般的COM模块都是使用regsvr32程序注册到注册表中,该程序在注册时会在模块中查找DllRegisterServer函数,卸载时调用模块中提供的DllUnregisterServer,所以要实现注册的功能主要需要实现这两个函数

这两个函数的原型如下:

STDAPI DllRegisterServer();
STDAPI DllUnregisterServer();

通过VS的F12功能查找STDAPI 的定义如下:

#define STDAPI  EXTERN_C HRESULT STDAPICALLTYPE

在查看STDAPICALLTYPE得到如下结果:

#define STDAPICALLTYPE          __stdcall

所以这个宏展开也就是

extern "C" HRESULT __stdcall DllRegisterServer();

为了实现注册功能,首先定义一个全局的变量,用来表示需要写入到注册表中的项

const TCHAR *g_regTable[][3] = {
{_T("SOFTWARE\\ComDemo"), 0, _T("ComDemo")},
{_T("SOFTWARE\\ComDemo\\InporcServer32"), 0, (const TCHAR*)-1}

这三项分别为注册表项,注册表项中的键名和键值,当键名为0时会创建一个默认的注册表键,最后一个-1我们会在程序中判断,如果键值为-1,那么值取为模块的路径

下面是注册的函数

STDAPI DllRegisterServer()
{
HKEY hKey = NULL;
TCHAR szFileName[MAX_PATH] = _T("");
GetModuleFileName(g_hDllIns, szFileName, MAX_PATH); int nCount = sizeof(g_regTable) / sizeof(*g_regTable);
for (int i = 0; i < nCount; i++)
{
LPCTSTR pszKeyName = g_regTable[i][0];
LPCTSTR pszValueName = g_regTable[i][1];
LPCTSTR pszValue = g_regTable[i][2];
if (pszValue == (const TCHAR*)-1)
{
pszValue = szFileName;
} long err = RegCreateKey(HKEY_LOCAL_MACHINE, pszKeyName, &hKey);
if (err != ERROR_SUCCESS)
{
return SELFREG_E_LAST;
} err = RegSetValueEx(hKey, pszValueName, 0, REG_SZ, (const BYTE*)pszValue, _tcslen(pszValue) * sizeof(TCHAR));
if (err != ERROR)
{
return SELFREG_E_LAST;
} RegCloseKey(hKey);
} return S_OK;
}

在程序中会循环读取上述全局变量中的值,将值保存到注册表中,在上面的代码中有一句sizeof(g_regTable) / sizeof(*g_regTable);

这个是算需要循环多少次,第一个sizeof得到的是这个二维数组的总大小。在C语言中我们说二维数组可以看做是由一维数组组成的,这个二维数组可以看成是由两个一维数组——一个由3个const TCHAR *成员组成的一维数组组成。所以*g_regTab自然就是这个一维数组的首地址,第二个sizeof就是这个一维数组的大小,两个相除得到的就是一维数组的个数。

卸载函数如下:

STDAPI DllUnregisterServer()
{
int nCount = sizeof(g_regTable) / sizeof(*g_regTable);
for (int i = nCount - 1; i >= 0; i--)
{
LPCTSTR pszKeyName = g_regTable[i][0];
long err = RegDeleteKey(HKEY_LOCAL_MACHINE, pszKeyName);
if (err != ERROR_SUCCESS)
{
return SELFREG_E_LAST;
}
} return S_OK;
}

至此已经实现注册和卸载函数。后面就可以直接使用regsvr32这个程序进行注册和卸载了.

COM学习(二)——COM的注册和卸载的更多相关文章

  1. SpringCloud 学习(二) :服务注册与发现Eureka

    Spring Cloud应用中可以支持多种的服务治理框架,比如Eureka.Consul.Zookeeper等,现在我们用的是consul,本文以SpringCloud Dalston.SR5版本介绍 ...

  2. 【Spring Cloud学习之二】服务注册和发现

    环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 Spring Cloud 1.2 一.EurekaEureka是Netflix开源的一个RESTful服务,主要用于服 ...

  3. SpringMVC入门学习(二)

    SpringMVC入门学习(二) ssm框架 springMVC  在上一篇博客中,我简单介绍了一下SpringMVC的环境配置,和简单的使用,今天我们将进一步的学习下Springmvc的操作. mo ...

  4. emberjs学习二(ember-data和localstorage_adapter)

    emberjs学习二(ember-data和localstorage_adapter) 准备工作 首先我们加入ember-data和ember-localstorage-adapter两个依赖项,使用 ...

  5. Quartz学习--二 Hello Quartz! 和源码分析

    Quartz学习--二  Hello Quartz! 和源码分析 三.  Hello Quartz! 我会跟着 第一章 6.2 的图来 进行同步代码编写 简单入门示例: 创建一个新的java普通工程 ...

  6. SpringCloud学习(二):微服务入门实战项目搭建

    一.开始使用Spring Cloud实战微服务 1.SpringCloud是什么? 云计算的解决方案?不是 SpringCloud是一个在SpringBoot的基础上构建的一个快速构建分布式系统的工具 ...

  7. DjangoRestFramework学习二之序列化组件、视图组件 serializer modelserializer

      DjangoRestFramework学习二之序列化组件.视图组件   本节目录 一 序列化组件 二 视图组件 三 xxx 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 序列化组 ...

  8. day 90 DjangoRestFramework学习二之序列化组件

      DjangoRestFramework学习二之序列化组件   本节目录 一 序列化组件 二 xxx 三 xxx 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 序列化组件 首先按照 ...

  9. SpringCloud(二)- 服务注册与发现Eureka

    离上一篇微服务的基本概念已经过去了几个月,在写那篇博客之前,自己还并未真正的使用微服务架构,很多理解还存在概念上.后面换了公司,新公司既用了SpringCloud也用了Dubbo+Zookeeper, ...

随机推荐

  1. Unity 3D游戏开发引擎:最火的插件推荐

    摘要:为了帮助使用Unity引擎的开发人员制作更完美的游戏.我们精心挑选了十款相关开发插件和工具.它们是:2D Toolkit.NGUI.Playmaker.EasyTouch & EasyJ ...

  2. C++ Primer高速入门之三:几种常见的控制语句

    语句总是顺序运行的:第一条语句运行完了接着是第二条,第三条等等.这是最简单的情况,为了更好的控制语句的运行.程序设计语言提供了多种控制结构支持更为复杂的语句运行.我们就来看看C++ 提供的控制方式. ...

  3. Qt---自定义界面之 Style Sheet

    这次讲Qt Style Sheet(QSS),QSS是一种与CSS类似的语言,实际上这两者几乎完全一样.既然谈到CSS我们就有必要说一下盒模型. 1. 盒模型(The Box Model) 在样式中, ...

  4. F12调试模式下使用console自动提交

    F12调试模式下使用console自动提交(F12 的console->输入代码->按enter即可运行) 1.使用定时器setInterval进行自动提交 //方法中可使用jquery调 ...

  5. 五、Spring Boot 事务

    spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactio ...

  6. 结对编程-四则运算GUI的实现

    一.项目成员以及coding地址: 洪灏捷(本人)201321122020  coding地址:https://git.coding.net/hoje/The-GUI-operation.git 白至 ...

  7. anaconda不能安装python的包问题

    在点了n次,重启应用多次之后,安装包(apply)之后还是没有反应,依然心平气和的我突然想到用管理员模式打开,结果就可以愉快的装包了,估计创建新的环境也是要管理员打开的.

  8. CS:APP3e 深入理解计算机系统_3e Datalab实验

    由于http://csapp.cs.cmu.edu/并未完全开放实验,很多附加实验做不了,一些环境也没办法搭建,更没有标准答案.做了这个实验的朋友可以和我对对答案:) 实验内容和要求可在http:// ...

  9. jQuery:deferred [转]

    jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本. 每个版本都会引入一些新功能.今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. ...

  10. ASP.NET.Core中使用AutoMapper

      首先需要在NuGet中引用AutoMapper的类库 install-package AutoMapper install-package AutoMapper.Extensions.Micros ...