一个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; }
相关推荐
13.如何取消COM服务组件注册?(Visual C++编程 源代码)13.如何取消COM服务组件注册?(Visual C++编程 源代码)13.如何取消COM服务组件注册?(Visual C++编程 源代码)13.如何取消COM服务组件注册?(Visual C++...
查看器 查看电脑中注册了那些组件 枚举了所有的组件注册信息
有两种方式注册组件: 一种是调用regsvr32.exe: 例如我们运行regsvr32.exe c:\test.dll来注册位于C:盘根目录下的test.dll。 逆@风@者 另外一种是在MTS(微软事务服务器)中注册。MTS是值得推荐的,因为它具有下列...
注册COM服务组件 注册COM服务组件 注册COM服务组件 注册COM服务组件 注册COM服务组件
COM+组件注册方法 regsvr32.exe
用于注册.ocx,.dll的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 然后回车,显示注册成功
众所周知,通过Assembly Manifests,我们可以免注册调用各种进程内的COM组件,包括DLL组件和OCX控件等。这里提供一个用于快速创建Assembly Manifest文件的工具。这个工具本身就是通过Assembly Manifests来免注册调用...
组件注册器 用来进行com组件在vista中注册,解决某些组件在vista下手工注册失败的问题。
选择com 后自动注册com 组件的程序
易语言组件注册工具OCX注册DLL注册源码,彗星注册组件,彗星卸载组件,彗星信息框,GetProcAddress,LoadLibrary,FreeLibrary,CallWindowProc,MessageBox,GetShortPathName
取消COM服务组件注册 取消COM服务组件注册 取消COM服务组件注册 取消COM服务组件注册
C# com 组件注册及调用 好用的案例调用将COM注册,方便使用很好的,对初学者来说很好,可以下载过来学习
包含com口组件dll,和注册表注册工具,和执行注册的bat可执行程序,自动注册,免去人工通过dos命令的繁琐工作。
组件注册工具
COM组件开发COM组件开发
通过一个简单的组件实现两个接口,CoCreateInstance 调用 DLLGetClassObject返回相应的组件类厂 类厂调用CreateInstance创建组件 用DLLRegisterServer向注册表中加一个组件ID,前提是要对注册表中CLSID下的结构有...
delphi实现COM组件的自动注册与卸载,源码实现加详解。
com组件学习com组件学习