`

COM组件注册真相

    博客分类:
  • COM+
 
阅读更多

       一个COM组件在使用前必须首先注册。所谓“注册”,也就是向系统注册表的相应位置写入一些数据。这些数据可以完成guid与Dll的绝对路径的一一对应,也就是说可以帮助程序通过guid找到Dll的位置。     
GUID概念:
       GUID(globally unique identifier)是一个128位的数。用于保证每一个接口和组件在时间和空间上都是全球唯一的一个标识符。为保证空间唯一性,根据机器上网卡的MAC地址再加上一定的算法生成的唯一的48位值序列;为保证时间上的唯一性,每个GUID值具有一个60位的时间戳。这个时间戳表示的是自1852年10月15号00:00:00以来以100纳秒为时间间隔的计数值。这样可以保证3400年GUID值仍然是唯一的。下面是GUID的定义和一个示例:

 

typedef struct _GUID {
    unsigned long  Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char  Data4[8];
} GUID;

// {364ede61-08ac-43ec-8861-15f5f9f4ced1}

 

 

微软提供了两个建立GUID的程序,一个时UUIDGEN.EXE,该程序是命令行方式的;另一个则是GUIDGEN.EXE,是一个示例性的VC++对话框应用。

DEFINE_GUID可以使用GUIDGEN.EXE来生成一个GUID。

 

注册表:

      组件可以用CLSID作为索引在Windows的注册表中发布包含他们的DLL文件名称。CoCreateInstance将用CLSID作为关键字在注册表中查找所需要的文件名称。注册表是一个由许多元素构成的层次结构。每一个元素均被称作是一个关键字。每一个关键字可以包含一系列子关键字、一系列命名的值及/或一个未命名的值。COM只使用了注册表的一个分支:HKEY_CLASSES_ROOT;在此关键字之下,可以看到有一个CLSID关键字。在CLSID关键字之下列有系统中安装的所有组件的CLSID。

对于每一个CLSID关键字,我们现在关心的只是它的一个子关键字InprocServer32。

此子关键字的缺省值是组件所在的Dll文件路径名称。

另一个子关键字ProgID指的是程序员给某个CLSID指定的一个程序员易记的名称。

 

如何注册COM组件:

      由于DLL知道它所包含的组件,因此DLL可以完成这些信息的注册。在DLL中一定要处处如下两个函数:

DllRegisterServer();// 完成注册组件

DllUnRegisterServer();// 完成反注册组件

用户可以使用程序REGSVR32.EXE来注册某个组件。方法是使用命令行:regsvr32/u testDll.dll(反注册)   regsvr32 testDll.dll(注册)。

 

一个典型的注册COM组件Dll必须导出如下五个函数:

1)DllMain:Dll的入口函数,完成一些Dll的初始化工作(DirectShow实现的是DllEntryPoint);

2)DllGetClassObject:用于获得类工厂指针;

3)DllCanUnloadNow: 系统空闲时会调用这个函数,以确定是否可以卸载Dll;

4)DllRegisterServer:将COM组件注册到注册表中;

5)DllUnregisterServer: 删除注册表中COM组件的注册信息。

所以,要想完成注册,关键就是对DllRegisterServer();DllUnRegisterServer();两个函数的实现,下面将详细介绍如何实现这两个函数:

 

//g_module为DLL的实例句柄
//CLSID_INNER_COM为组件的CLSID
//const char g_friend_name_inner [] = "inner_com_test";
//const char g_ver_indprog_id_inner [] = "inside.com.chapter.7.inner";
//const char g_prog_id_inner [] = "inside.com.chapter.7.inner.1";
STDAPI DllRegisterServer(void)
{
    HRESULT hr = RegisterServer(g_module,CLSID_INNER_COM,
        g_friend_name_inner,g_ver_indprog_id_inner,g_prog_id_inner);
    
    return hr;
}
//Register the component in the registry
HRESULT RegisterServer(HMODULE hModule,
                                             const CLSID& clsid,
                                             const char* szFriendlyName,
                                             const char* szVerIndProgID,
                                             const char* szProgID)
{
    //Get the Server location
    char szModule[512];
    DWORD dwResult = ::GetModuleFileName(hModule,szModule,sizeof(szModule)/sizeof(char));
    assert(dwResult!=0);

    //Convert the CLSID into a char
    char szCLSID[CLSID_STRING_SIZE];
    CLSIDtochar(clsid,szCLSID,sizeof(szCLSID));

    //Build the key CLSID\\{}
    char szKey[64];
    strcpy(szKey,"CLSID\\");
    strcat(szKey,szCLSID);

    //Add the CLSID to the registry
    setKeyAndValue(szKey,NULL,szFriendlyName);

    //Add the Server filename subkey under the CLSID key
    setKeyAndValue(szKey,"InprocServer32",szModule);

    setKeyAndValue(szKey,"ProgID",szProgID);

    setKeyAndValue(szKey,"VersionIndependentProgID",szVerIndProgID);

    //Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT
    setKeyAndValue(szVerIndProgID,NULL,szFriendlyName);
    setKeyAndValue(szVerIndProgID,"CLSID",szCLSID);
    setKeyAndValue(szVerIndProgID,"CurVer",szProgID);

    //Add the versioned ProgID subkey under HKEY_CLASSES_ROOT
    setKeyAndValue(szProgID,NULL,szFriendlyName);
    setKeyAndValue(szProgID,"CLSID",szCLSID);
    return S_OK;
}
STDAPI DllUnregisterServer(void)
{
    HRESULT hr =  UnRegisterServer(CLSID_INNER_COM,g_ver_indprog_id_inner,g_prog_id_inner);

    return hr;
}
//Remove the component from the register
HRESULT UnRegisterServer(const CLSID& clsid,           // Class ID
                                                 const char* szVerIndProgID,   // Programmatic
                                                 const char* szProgID)           // IDs
{
    //Convert the CLSID into a char.
    char szCLSID[CLSID_STRING_SIZE];
    CLSIDtochar(clsid,szCLSID,sizeof(szCLSID));

    //Build the key CLSID\\{}
    char szKey[64];
    strcpy(szKey,"CLSID\\");
    strcat(szKey,szCLSID);

    //Delete the CLSID key - CLSID\{}
    LONG lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT,szKey);
    assert((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND));

    //Delete the version-independent ProgID Key
    lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT,szVerIndProgID);
    assert((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND));

    //Delete the ProgID key.
    lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT,szProgID);
    assert((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND));

    return S_OK;
}

 

分享到:
评论

相关推荐

    com组件注册查看器

    "com组件注册查看器"是一个专门用于查看计算机上已注册的COM组件的工具。通过这款查看器,用户可以枚举并查看所有已注册的COM组件的相关信息,这包括但不限于组件的CLSID(Class ID)、ProgID(Program ID)、文件...

    COM+组件注册方法

    COM+组件注册是Windows操作系统中用于管理分布式组件的一种机制,它扩展了传统的COM(Component Object Model)技术,提供了更高级别的服务,如事务处理、安全性和资源管理。COM+组件通常用于构建分布式应用程序,使...

    COM 组件注册方法

    注册COM组件是使其能够被系统识别并可供其他程序使用的必要步骤。 在Windows操作系统中,注册COM组件通常有两种方法: 1. **调用regsvr32.exe**: 这是传统且最直接的方法,通过命令行执行`regsvr32.exe`命令,将...

    13.如何取消COM服务组件注册?(Visual C++编程 源代码)

    13.如何取消COM服务组件注册?(Visual C++编程 源代码)13.如何取消COM服务组件注册?(Visual C++编程 源代码)13.如何取消COM服务组件注册?(Visual C++编程 源代码)13.如何取消COM服务组件注册?(Visual C++...

    com口组件与com口注册工具32/64位

    在给定的“com口组件与com口注册工具32/64位”压缩包中,包含了以下关键内容: 1. **COM口组件DLL**:DLL (Dynamic Link Library) 文件是一种包含可由多个程序同时使用的代码和数据的库。在本案例中,这个DLL文件...

    C# com 组件注册及调用

    本文将深入探讨C#中如何创建、注册COM组件以及如何在其他应用程序中调用这些组件,这对于初学者来说是一次宝贵的学习机会。 首先,我们需要理解什么是COM组件。COM是微软提出的一种二进制标准,它允许不同语言编写...

    注册com组件

    注册COM组件是将这些组件与系统进行关联的过程,以便Windows能够识别并正确地调用它们。 注册COM组件通常涉及到以下步骤: 1. **创建COM组件**:开发者使用编程语言(如C++、VB或Delphi)创建一个实现了特定接口的...

    易语言组件注册工具OCX注册DLL注册

    易语言组件注册工具OCX注册DLL注册源码,彗星注册组件,彗星卸载组件,彗星信息框,GetProcAddress,LoadLibrary,FreeLibrary,CallWindowProc,MessageBox,GetShortPathName

    C#_COM组件注册与调用

    安装了VS(我用的vs2012 64位) gacutil.exe路径 C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools ...3、regasm dll文件名.dll /tlb:dll文件名.tlb 然后回车,显示注册成功

    delphi实现COM组件的自动注册与卸载

    本篇文章将深入探讨如何使用Delphi来实现COM组件的自动注册与卸载。 首先,COM组件的注册是将其元数据(如类ID、接口ID等)写入系统注册表的过程,以便其他应用程序能够找到并使用这些组件。在Delphi中,我们通常会...

    免注册调用COM组件方法二-Assembly Manifests

    众所周知,通过Assembly Manifests,我们可以免注册调用各种进程内的COM组件,包括DLL组件和OCX控件等。这里提供一个用于快速创建Assembly Manifest文件的工具。这个工具本身就是通过Assembly Manifests来免注册调用...

    c++开发一个简单累加的COM组件

    1. 注册COM组件:编译运行项目,生成dll文件,并自动注册到系统中。 2. 使用MFC调用COM组件:使用ClassWizard生成包装类,使用类型库中的MFC类来调用COM组件。 3. 使用COM组件:在对话框程序中,引入头文件#...

    VS 2015 C# COM组件开发实例和注册使用实例.rar

    在本实例中,我们将探讨如何使用Visual Studio 2015(VS 2015)和C#语言来创建一个COM组件,并了解其注册和使用的步骤。 首先,创建COM组件需要一个支持COM的项目类型。在VS 2015中,我们可以创建一个“类库”项目...

    c#中调用com组件

    每个COM组件都必须注册到系统中才能被其他应用程序所使用,这个过程通常通过`regsvr32`命令完成。 #### 实现步骤 根据题目中的部分描述和内容,下面将详细介绍如何在C#中调用COM组件。 ##### 步骤一:注册COM组件...

    WPF调用COM组件

    - 注册COM组件以便其他程序可以找到和使用它。 2. 在WPF中调用COM组件: - 在WPF应用中添加对`System.Runtime.InteropServices`命名空间的引用,这是.NET框架提供的COM互操作性支持。 - 使用`[DllImport]`或`...

    C#编写COM组件示例

    - 使用regasm工具将.NET程序集注册为COM组件,使其能够在系统注册表中注册组件信息。 - 上述步骤后,COM组件就可以被其他应用程序通过其ProgID进行创建和使用了。 ***组件的调用示例 - 在VBScript中,可以使用...

    vb.net 封装组件成com的方法

    下面我们将详细探讨如何在VB.NET中创建和注册一个COM组件。 1. **创建VB.NET类库项目** 首先,我们需要在Visual Studio中创建一个新的VB.NET Class Library项目。这可以通过选择“文件” > “新建” > “项目”,...

    用C#创建COM组件全过程

    通过这篇文章,读者可以了解COM组件的基本概念,如何新建一个Visual C#工程,编写导出接口,创建事件接口,创建具体类,注册COM组件,并使用VC6.0调用COM组件。 九、注意事项 在编写COM组件时,需要注意以下几点:...

    检索com类工厂中组件注册失败的解决方法

    ### 检索COM类工厂中组件注册失败的解决方法 在进行软件开发或系统管理过程中,有时会遇到“检索COM类工厂中组件注册失败”的问题,尤其在尝试注册Office组件(如Microsoft Excel)时较为常见。这类问题往往与...

    WIN32 COM组件 的实现及注册

    通过一个简单的组件实现两个接口,CoCreateInstance 调用 DLLGetClassObject返回相应的组件类厂 类厂调用CreateInstance创建组件 用DLLRegisterServer向注册表中加一个组件ID,前提是要对注册表中CLSID下的结构有...

Global site tag (gtag.js) - Google Analytics