我是属于驱动型的人,无法自主的去做某事。只有等到火烧眉头才知道着急。
现在社会技术的发展也是在被商业用途所驱动着,只要有着广阔的商业前景的技术,其发展必然叙述。
在学习COM技术的时候,也是首先要知道我能够用他来干什么,对我有什么用,才会去学。于是,学习时就要先看看如果给我一个
现成COM组件我该怎么使用它呢。好比,要写游戏就要先玩玩游戏一样了。
于是有了下面的COM组件的使用,也是个人在学习时梳理学习思路:
COM组件其实并不复杂,也就是一个特殊的DLL而已。但是一般的DLL我们只要知道它导出了哪些函数。我们该怎样调用即可。
而COM组件,我们的目的不是使用它导出的函数,而是要利用它来实现某个具体的功能。
一般来说,COM组件的DLL导出的函数一般有
DllCanUnloadNow
DllGetClassObject
DllRegisterServer
DllUnregisterServer
函数。当然不是必须的。其中DllRegisterServer和DllUnregisterServer是用来将COM组件注册到系统中。至于其他的函数以后学
习中在说。既然是说COM组件在客户端的使用。就开始了。
首先。COM组件在注册表中注册,就是把组件的代号写在注册表中。该代号就是在写组件时给定的。然后注册时就是告诉系统该代号对应的组件在系统中的什么位置,以及该组件名称是什么。比如在我的系统中有一个组件是COM.dll,在编写主键的时候已确定其
GUID是54BF6563-1007-11D1-B0AA-444553540000,组件名是server.object.在使用Regsvr32 COM.dll注册后,就会在
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\下生成一子项为:{54BF6563-1007-11D1-B0AA-444553540000},该子项下又对应两个子项:InProcServer32和ProgID通过注册表导出得到该组件注册后注册表信息为:
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{54BF65 63-1007-11D1-B0AA-444553540000}]
@="server.object"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{54BF65 63-1007-11D1-B0AA-444553540000}\InProcServer32]
@="E:\\PROGRA~1\\MICROS~1\\MYPROJ~1\\COM\\Debug\\c om.dll"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{54BF65 63-1007-11D1-B0AA-444553540000}\ProgID]
@="server.object"
注册后的组件就可以被客户端使用了。在程序代码中。要使用COM组件。首先调用CoInitialize()函数进行初始化COM库工作。
与其对应的是在使用完成后调用CoUninitialize()清理COM环境。 一般来说,组件的{54BF6563-1007-11D1-B0AA-444553540000}是唯一的。可以直接使用它来创建组件实例,查找组件接口。但是由于该值不容易记忆。一般使用其ProgID值来间接查找。其中通过函数CLSIDFromProgID 来转换。记忆ProgID这样一个有意思的字符串就比较容易了。下面是是一个使用实例。集合注释很清楚的表示了使用过程。int main() { HRESULT hResult = 0; IUnknown *pUnknown; ITestInterFace* pTestCom;//接口指针 if (CoInitialize(NULL) != S_OK) //初始化COM库 printf("Initialize COM library failed!\n"); return -1; } GUID TestComCLSID;//组件标识ID,全球唯一,在注册表中可以直接查找到 //TestCom.Object是注册表中的ProgID的值,通过它就可以查找到组件的标识ID hResult = ::CLSIDFromProgID(L"TestCom.Object", &TestComCLSID); if (hResult != S_OK) { printf("Can't find the TestCom CLSID!\n"); return -2; } //通过组件标识ID创建一个组件实例,pUnknown返回组件的一个通用接口,通过它 //可以查询我们想要的接口 //CLSTX_INPROC_SERVER表示是进程类主键 //其实此处也通过InProcServer32查找到组件的路径并加载到内存 hResult = CoCreateInstance(TestComCLSID, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnknown); if (hResult != S_OK) { printf("Create object failed!\n"); return -2; } //查找要使用的接口,IDD_TestCom是组件的标识符,通过该标识符也就查找到对应的接口了 //该标识符由服务端组件告知,否则写的组件也就失去其意义。 hResult = pUnknown->QueryInterface(IID_TestCom, (void **)&pTestCom); if (hResult != S_OK) { pUnknown->Release(); printf("QueryInterface ITestInterFace failed!\n"); return -3; } //查找到接口后调用接口提供的功能 pTestCom->TestCom(); //告诉接口,不在使用 pTestCom->Release(); //判断该接口是否还被使用 if (pUnknown->Release() == 0) { printf("Com Free Succeeded!\n"); } //清理环境 CoUninitialize(); return 0; } 整个组件的使用过程如代码中所示,很简单。恩,有了饭,还怕不会吃吗,开始还是会怯生,一回生二回熟吧。
现在社会技术的发展也是在被商业用途所驱动着,只要有着广阔的商业前景的技术,其发展必然叙述。
在学习COM技术的时候,也是首先要知道我能够用他来干什么,对我有什么用,才会去学。于是,学习时就要先看看如果给我一个
现成COM组件我该怎么使用它呢。好比,要写游戏就要先玩玩游戏一样了。
于是有了下面的COM组件的使用,也是个人在学习时梳理学习思路:
COM组件其实并不复杂,也就是一个特殊的DLL而已。但是一般的DLL我们只要知道它导出了哪些函数。我们该怎样调用即可。
而COM组件,我们的目的不是使用它导出的函数,而是要利用它来实现某个具体的功能。
一般来说,COM组件的DLL导出的函数一般有
DllCanUnloadNow
DllGetClassObject
DllRegisterServer
DllUnregisterServer
函数。当然不是必须的。其中DllRegisterServer和DllUnregisterServer是用来将COM组件注册到系统中。至于其他的函数以后学
习中在说。既然是说COM组件在客户端的使用。就开始了。
首先。COM组件在注册表中注册,就是把组件的代号写在注册表中。该代号就是在写组件时给定的。然后注册时就是告诉系统该代号对应的组件在系统中的什么位置,以及该组件名称是什么。比如在我的系统中有一个组件是COM.dll,在编写主键的时候已确定其
GUID是54BF6563-1007-11D1-B0AA-444553540000,组件名是server.object.在使用Regsvr32 COM.dll注册后,就会在
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\下生成一子项为:{54BF6563-1007-11D1-B0AA-444553540000},该子项下又对应两个子项:InProcServer32和ProgID通过注册表导出得到该组件注册后注册表信息为:
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{54BF65 63-1007-11D1-B0AA-444553540000}]
@="server.object"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{54BF65 63-1007-11D1-B0AA-444553540000}\InProcServer32]
@="E:\\PROGRA~1\\MICROS~1\\MYPROJ~1\\COM\\Debug\\c om.dll"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{54BF65 63-1007-11D1-B0AA-444553540000}\ProgID]
@="server.object"
注册后的组件就可以被客户端使用了。在程序代码中。要使用COM组件。首先调用CoInitialize()函数进行初始化COM库工作。
与其对应的是在使用完成后调用CoUninitialize()清理COM环境。 一般来说,组件的{54BF6563-1007-11D1-B0AA-444553540000}是唯一的。可以直接使用它来创建组件实例,查找组件接口。但是由于该值不容易记忆。一般使用其ProgID值来间接查找。其中通过函数CLSIDFromProgID 来转换。记忆ProgID这样一个有意思的字符串就比较容易了。下面是是一个使用实例。集合注释很清楚的表示了使用过程。int main() { HRESULT hResult = 0; IUnknown *pUnknown; ITestInterFace* pTestCom;//接口指针 if (CoInitialize(NULL) != S_OK) //初始化COM库 printf("Initialize COM library failed!\n"); return -1; } GUID TestComCLSID;//组件标识ID,全球唯一,在注册表中可以直接查找到 //TestCom.Object是注册表中的ProgID的值,通过它就可以查找到组件的标识ID hResult = ::CLSIDFromProgID(L"TestCom.Object", &TestComCLSID); if (hResult != S_OK) { printf("Can't find the TestCom CLSID!\n"); return -2; } //通过组件标识ID创建一个组件实例,pUnknown返回组件的一个通用接口,通过它 //可以查询我们想要的接口 //CLSTX_INPROC_SERVER表示是进程类主键 //其实此处也通过InProcServer32查找到组件的路径并加载到内存 hResult = CoCreateInstance(TestComCLSID, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnknown); if (hResult != S_OK) { printf("Create object failed!\n"); return -2; } //查找要使用的接口,IDD_TestCom是组件的标识符,通过该标识符也就查找到对应的接口了 //该标识符由服务端组件告知,否则写的组件也就失去其意义。 hResult = pUnknown->QueryInterface(IID_TestCom, (void **)&pTestCom); if (hResult != S_OK) { pUnknown->Release(); printf("QueryInterface ITestInterFace failed!\n"); return -3; } //查找到接口后调用接口提供的功能 pTestCom->TestCom(); //告诉接口,不在使用 pTestCom->Release(); //判断该接口是否还被使用 if (pUnknown->Release() == 0) { printf("Com Free Succeeded!\n"); } //清理环境 CoUninitialize(); return 0; } 整个组件的使用过程如代码中所示,很简单。恩,有了饭,还怕不会吃吗,开始还是会怯生,一回生二回熟吧。