这就是com组件

来源:互联网 发布:雅文go淘宝返利真假? 编辑:程序博客网 时间:2024/06/05 11:34

【VS开发】这就是COM组件

13人阅读 评论(0)收藏举报
本文章已收录于:
分类:
作者同类文章X

    [实例]这就是COM组件

    [实例]这就是COM组件

    Author: ume Date:2012-02-21

        自从微软推出.NET以来,COM技术就渐渐淡出人们的视野,然而这并不意味COM不再发挥作用,相反,COM非常重要。可以说.NET的实现离不开COM的支撑。COM是好东西,但是它太难了,不利于产品推广,于是微软只能在之上增加一层封装从而提高产品的易用性。对COM有所了解是很有必要的,希望这篇文章给你带来一点启发。

    1. COM的思想

        开篇就讲COM的思想肯定让人泄气,因为它极有可能抽象空洞、晦涩难懂。换个角度来说,我觉得COM的思想仍然是需要自己去体会的,这里给出的不过是一个思考的线索而已,你大可不求甚解。

        软件的开发是永无止境的,只要软件还在存活期,它就应当不断被完善和更新。一款软件可能十分庞大,但真正可变的部分却是很有限的。我们当然希望在更新软件的时候,只更新变化的部分,而不要笨手笨脚把整个软件都换掉。只更新变化的部分?这就要求模块支持动态链接。所谓动态链接就是模块只在被使用的时候才被加载,程序调用模块中的某个函数是通过指针来完成的。动态链接允许模块分离出去,而不像静态链接那样须经过编译才能整合到程序中来。dll是实现动态链接的一种方法,它使更新软件的工作浓缩成了更新dll,用户无需重新安装软件,只需替换相应的dll文件就能实现软件的升级。

        动态链接是针对普通用户而言的,现在换一个对象:模块的用户。模块的用户是应用程序开发人员,对于模块的提供商来说也算得上同行了,只不过术业有专攻,各自工作的重点不同而已。显然采用dll的形式,模块的提供商可以很方便的发布自己的产品。其中不可忽视的另一点即信息的封装(或称隐藏),即将模块的实现细节隐蔽起来,用户无法知道模块的提供商采用何种语言、何种算法,简而言之就是用户看不到模块的源代码。dll是二进制级别上的代码复用,它实现了信息的封装。

        综上所述,软件开发要求模块支持“动态链接”和“信息封装”,更直白地说就是要求模块和客户代码之间更低的耦合度。把模块制作成组件是必然的选择,而COM本质上是一种创建组件的方法和规范。

        注:dll并不等同于组件,它只是组件的一种形式。由于dll的易用性,它的应用很广泛。

    2. 实例说明

        我们创建一个COM组件,它将实现接口ICouplet,用户可通过该接口调用what()方法输出一副对联。what()方法不值一提,不过你可以将它当作程序可变的部分。我们创建的COM组件也要实现接口IClassFactory,它是创建组件的简单组件。之所以这么设计是为了让组件与客户代码彻底脱耦,尽可能少的联系。

        除了实现接口ICouplet和IClassFactory外, COM组件还要能实现自注册,因此它必须导出函数DllRegister/DllUnregister。另外两个导出函数DllCanUnloadNow和DllGetClassObject也非常重要,前者用来询问当前dll能否被卸载,它被CoFreeUnusedLibraries调用;后者用来创建类厂组件,它被CoCreateInstance调用。名称形如Coxxx的函数是COM库函数,它是实现COM组件的公共操作,由微软提供,类似于Win32 API。我们常见的客户代码中CoInitialize/CoUninitialize函数就起到初始化和卸载COM库的作用。要导出上述4个函数就必须编写一个.def文件,具体写法见代码清单。

        最后要说明的是COM组件的自注册。我们知道注册表是Windows的公共系统数据库,其中记录了软件、硬件、用户配置等信息。而COM组件是用一个128比特的GUID标识的,为了使得COM组件的安装目录更灵活,我们可以在注册表中对它进行注册,注册的主要信息即COM组件的GUID标识与其存储路径的对应关系,在使用该组件时就到注册表中去查找。注册一个COM组件一般使用regsvr32.exe程序来完成,当然你也可以自己写一个类似于regsvr32.exe的小程序来完成COM组件的注册,regsvr32.exe本质上调用了组件的导出函数DllRegister/DllUnregister。

        生成Couplet.dll文件后,首先在控制台注册它。具体方法:切换到Couplet.dll所在目录,输入指令regsvr32 Couplet.dll。然后运行客户程序Reader.exe,其结果如下所示:

    <span class="operator"><span class="keyword" style="font-weight:bold">Create</span> Couplet objectSucceeded <span class="keyword" style="font-weight:bold">in</span> getting the pointer <span class="keyword" style="font-weight:bold">to</span> ICouplet<span class="number" style="color:rgb(0,153,153)">1</span>st <span class="keyword" style="font-weight:bold">Scroll</span>: Study Hard, <span class="keyword" style="font-weight:bold">Work</span> Hard, Make Money More <span class="keyword" style="font-weight:bold">and</span> More<span class="number" style="color:rgb(0,153,153)">2</span>nd <span class="keyword" style="font-weight:bold">Scroll</span>: Eat Well, Sleep Well, Have Fun <span class="keyword" style="font-weight:bold">Day</span> <span class="keyword" style="font-weight:bold">by</span> <span class="keyword" style="font-weight:bold">Day</span>Top <span class="keyword" style="font-weight:bold">Scroll</span>: GelievableCouplet object deleted请按任意键继续. . .</span>

        然后修改Couplet::what()方法,让它输出中文,重新生成Couplet.dll。这一步不用重新注册Couplet.dll,因为Couplet.dll的路径没变,CLSID_Couplet也没变。运行客户程序Reader.exe,其结果如下所示:

    CreateCouplet <span class="keyword" style="font-weight:bold">object</span>Succeededin getting the pointer to ICouplet 上联:我爱的人名花有主下联:爱我的人惨不忍睹横批:命苦 Coupletobject deleted请按任意键继续. . .

        这个例子证明了COM组件的更新不会对客户端造成影响,使用COM组件可以实现模块与客户代码彻底脱耦。实验结束后,在控制台输入指令regsvr32 /u Couplet.dll,从注册表中将dll模块信息清除。

    3. 代码清单

    <span class="comment" style="color:rgb(153,153,136); font-style:italic">/* File List: (COM) IFace.h Register.h Register.cpp Couplet.cpp Couple.def *           (Client) IFace.h Reader.cpp * date: 2012-02-21 * author: ume */</span><span class="comment" style="color:rgb(153,153,136); font-style:italic"><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span>//</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// IFace.h 接口的声明,组件ID、接口ID的定义</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">//</span><span class="preprocessor" style="color:rgb(153,153,153); font-weight:bold">#include <ObjBase.h></span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// interface</span><span class="keyword" style="font-weight:bold">interface</span> ICouplet : IUnknown{    <span class="keyword" style="font-weight:bold">virtual</span> <span class="keyword" style="font-weight:bold">void</span> what() = <span class="number" style="color:rgb(0,153,153)">0</span>;};<span class="comment" style="color:rgb(153,153,136); font-style:italic">// GUIDs</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// {03844548-B0B9-4B12-869D-061AAE2E4B7F}</span><span class="keyword" style="font-weight:bold">static</span> <span class="keyword" style="font-weight:bold">const</span> GUID IID_ICouplet = { <span class="number" style="color:rgb(0,153,153)">0x3844548</span>, <span class="number" style="color:rgb(0,153,153)">0xb0b9</span>, <span class="number" style="color:rgb(0,153,153)">0x4b12</span>, { <span class="number" style="color:rgb(0,153,153)">0x86</span>, <span class="number" style="color:rgb(0,153,153)">0x9d</span>, <span class="number" style="color:rgb(0,153,153)">0x6</span>, <span class="number" style="color:rgb(0,153,153)">0x1a</span>, <span class="number" style="color:rgb(0,153,153)">0xae</span>, <span class="number" style="color:rgb(0,153,153)">0x2e</span>, <span class="number" style="color:rgb(0,153,153)">0x4b</span>, <span class="number" style="color:rgb(0,153,153)">0x7f</span> } };<span class="comment" style="color:rgb(153,153,136); font-style:italic">// {26615B48-1D2E-4A40-9C07-AD5B1B48368C}</span><span class="keyword" style="font-weight:bold">static</span> <span class="keyword" style="font-weight:bold">const</span> GUID CLSID_Couplet = { <span class="number" style="color:rgb(0,153,153)">0x26615b48</span>, <span class="number" style="color:rgb(0,153,153)">0x1d2e</span>, <span class="number" style="color:rgb(0,153,153)">0x4a40</span>, { <span class="number" style="color:rgb(0,153,153)">0x9c</span>, <span class="number" style="color:rgb(0,153,153)">0x7</span>, <span class="number" style="color:rgb(0,153,153)">0xad</span>, <span class="number" style="color:rgb(0,153,153)">0x5b</span>, <span class="number" style="color:rgb(0,153,153)">0x1b</span>, <span class="number" style="color:rgb(0,153,153)">0x48</span>, <span class="number" style="color:rgb(0,153,153)">0x36</span>, <span class="number" style="color:rgb(0,153,153)">0x8c</span> } };<span class="comment" style="color:rgb(153,153,136); font-style:italic"><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span>//</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// Register.h 注册函数的声明</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">//</span>HRESULT RegisterServer(HMODULE hModule,                   <span class="keyword" style="font-weight:bold">const</span> CLSID& clsid,                   <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szFriendlyName,               <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szVerIndProgID,               <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szProgID);HRESULT UnRegisterServer(<span class="keyword" style="font-weight:bold">const</span> CLSID& clsid,            <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szVerIndProgID,             <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szProgID);<span class="comment" style="color:rgb(153,153,136); font-style:italic"><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span>//</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// Register.cpp 注册函数的定义</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// 这些函数可重复使用,非本文重点</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">//</span><span class="preprocessor" style="color:rgb(153,153,153); font-weight:bold">#include <objbase.h></span><span class="preprocessor" style="color:rgb(153,153,153); font-weight:bold">#include "Register.h"</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">//set the given key and its value;</span>BOOL setKeyAndValue(<span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* pszPath,                    <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szSubkey,                    <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szValue);<span class="comment" style="color:rgb(153,153,136); font-style:italic">//Convert a CLSID into a char string</span><span class="keyword" style="font-weight:bold">void</span> CLSIDtochar(<span class="keyword" style="font-weight:bold">const</span> CLSID& clsid,                 <span class="keyword" style="font-weight:bold">char</span>* szCLSID,                 <span class="keyword" style="font-weight:bold">int</span> length);<span class="comment" style="color:rgb(153,153,136); font-style:italic">//Delete szKeyChild and all of its descendents</span>LONG recursiveDeleteKey(HKEY hKeyParent,<span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szKeyChild);<span class="comment" style="color:rgb(153,153,136); font-style:italic">//size of a CLSID as a string</span><span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">int</span> CLSID_STRING_SIZE = <span class="number" style="color:rgb(0,153,153)">39</span>;<span class="comment" style="color:rgb(153,153,136); font-style:italic">//Register the component in the registry</span>HRESULT RegisterServer(HMODULE hModule,                       <span class="keyword" style="font-weight:bold">const</span> CLSID& clsid,                       <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szFriendlyName,                       <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szVerIndProgID,                       <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szProgID){    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Get the Server location</span>    <span class="keyword" style="font-weight:bold">char</span> szModule[<span class="number" style="color:rgb(0,153,153)">512</span>];    DWORD dwResult = ::GetModuleFileName(hModule,szModule,<span class="keyword" style="font-weight:bold">sizeof</span>(szModule)/<span class="keyword" style="font-weight:bold">sizeof</span>(<span class="keyword" style="font-weight:bold">char</span>));    assert(dwResult!=<span class="number" style="color:rgb(0,153,153)">0</span>);    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Convert the CLSID into a char</span>    <span class="keyword" style="font-weight:bold">char</span> szCLSID[CLSID_STRING_SIZE];    CLSIDtochar(clsid,szCLSID,<span class="keyword" style="font-weight:bold">sizeof</span>(szCLSID));    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Build the key CLSID\\{}</span>    <span class="keyword" style="font-weight:bold">char</span> szKey[<span class="number" style="color:rgb(0,153,153)">64</span>];    strcpy(szKey,<span class="string" style="color:rgb(221,17,68)">"CLSID\\"</span>);    strcat(szKey,szCLSID);    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Add the CLSID to the registry</span>    setKeyAndValue(szKey,NULL,szFriendlyName);    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Add the Server filename subkey under the CLSID key</span>    setKeyAndValue(szKey,<span class="string" style="color:rgb(221,17,68)">"InprocServer32"</span>,szModule);    setKeyAndValue(szKey,<span class="string" style="color:rgb(221,17,68)">"ProgID"</span>,szProgID);    setKeyAndValue(szKey,<span class="string" style="color:rgb(221,17,68)">"VersionIndependentProgID"</span>,szVerIndProgID);    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT</span>    setKeyAndValue(szVerIndProgID,NULL,szFriendlyName);    setKeyAndValue(szVerIndProgID,<span class="string" style="color:rgb(221,17,68)">"CLSID"</span>,szCLSID);    setKeyAndValue(szVerIndProgID,<span class="string" style="color:rgb(221,17,68)">"CurVer"</span>,szProgID);    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Add the versioned ProgID subkey under HKEY_CLASSES_ROOT</span>    setKeyAndValue(szProgID,NULL,szFriendlyName);    setKeyAndValue(szProgID,<span class="string" style="color:rgb(221,17,68)">"CLSID"</span>,szCLSID);    <span class="keyword" style="font-weight:bold">return</span> S_OK;}<span class="comment" style="color:rgb(153,153,136); font-style:italic">//</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">//Remove the component from the register</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">//</span>HRESULT UnRegisterServer(<span class="keyword" style="font-weight:bold">const</span> CLSID& clsid,           <span class="comment" style="color:rgb(153,153,136); font-style:italic">// Class ID</span>                         <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szVerIndProgID,   <span class="comment" style="color:rgb(153,153,136); font-style:italic">// Programmatic</span>                         <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szProgID)           <span class="comment" style="color:rgb(153,153,136); font-style:italic">// IDs</span>{    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Convert the CLSID into a char.</span>    <span class="keyword" style="font-weight:bold">char</span> szCLSID[CLSID_STRING_SIZE];    CLSIDtochar(clsid,szCLSID,<span class="keyword" style="font-weight:bold">sizeof</span>(szCLSID));    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Build the key CLSID\\{}</span>    <span class="keyword" style="font-weight:bold">char</span> szKey[<span class="number" style="color:rgb(0,153,153)">64</span>];    strcpy(szKey,<span class="string" style="color:rgb(221,17,68)">"CLSID\\"</span>);    strcat(szKey,szCLSID);    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Delete the CLSID key - CLSID\{}</span>    LONG lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT,szKey);    assert((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND));    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Delete the version-independent ProgID Key</span>    lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT,szVerIndProgID);    assert((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND));    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Delete the ProgID key.</span>    lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT,szProgID);    assert((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND));    <span class="keyword" style="font-weight:bold">return</span> S_OK;}<span class="comment" style="color:rgb(153,153,136); font-style:italic">//Convert a CLSID to a char string</span><span class="keyword" style="font-weight:bold">void</span> CLSIDtochar(<span class="keyword" style="font-weight:bold">const</span> CLSID& clsid,                 <span class="keyword" style="font-weight:bold">char</span>* szCLSID,                 <span class="keyword" style="font-weight:bold">int</span> length){    assert(length>=CLSID_STRING_SIZE);    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Get CLSID</span>    LPOLESTR wszCLSID = NULL;    HRESULT hr = StringFromCLSID(clsid,&wszCLSID);    assert(SUCCEEDED(hr));    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Convert from wide characters to non_wide</span>    wcstombs(szCLSID,wszCLSID,length);        <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Free memory</span>    CoTaskMemFree(wszCLSID);}<span class="comment" style="color:rgb(153,153,136); font-style:italic">// Delete a Key and all of its descendents</span>LONG recursiveDeleteKey(HKEY hKeyParent,<span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* lpszKeyChild){    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Open the child.</span>    HKEY hKeyChild;    LONG lRes = RegOpenKeyEx(hKeyParent,lpszKeyChild,<span class="number" style="color:rgb(0,153,153)">0</span>,KEY_ALL_ACCESS,&hKeyChild);    <span class="keyword" style="font-weight:bold">if</span>(lRes != ERROR_SUCCESS)        <span class="keyword" style="font-weight:bold">return</span> lRes;    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Enumerate all of the decendents of this child</span>    FILETIME time;    <span class="keyword" style="font-weight:bold">char</span> szBuffer[<span class="number" style="color:rgb(0,153,153)">256</span>];    DWORD dwSize = <span class="number" style="color:rgb(0,153,153)">256</span> ;        <span class="keyword" style="font-weight:bold">while</span>(RegEnumKeyEx(hKeyChild,<span class="number" style="color:rgb(0,153,153)">0</span>,szBuffer,&dwSize,NULL,        NULL,NULL,&time) == S_OK)    {        <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Delete the decendents of this child.</span>        lRes = recursiveDeleteKey(hKeyChild,szBuffer);        <span class="keyword" style="font-weight:bold">if</span>(lRes != ERROR_SUCCESS)        {            RegCloseKey(hKeyChild);            <span class="keyword" style="font-weight:bold">return</span> lRes;        }        dwSize = <span class="number" style="color:rgb(0,153,153)">256</span>;    }    RegCloseKey(hKeyChild);    <span class="keyword" style="font-weight:bold">return</span> RegDeleteKey(hKeyParent,lpszKeyChild);}BOOL setKeyAndValue(<span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szKey,                    <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szSubkey,                    <span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* szValue){    HKEY hKey;    <span class="keyword" style="font-weight:bold">char</span> szKeyBuf[<span class="number" style="color:rgb(0,153,153)">1024</span>];    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Copy keyname into buffer.</span>    strcpy(szKeyBuf,szKey);    <span class="comment" style="color:rgb(153,153,136); font-style:italic">//Add subkey name to buffer.</span>    <span class="keyword" style="font-weight:bold">if</span>(szSubkey!=NULL)    {        strcat(szKeyBuf,<span class="string" style="color:rgb(221,17,68)">"\\"</span>);        strcat(szKeyBuf,szSubkey);    }    <span class="comment" style="color:rgb(153,153,136); font-style:italic">// Create and open key and subkey.</span>    <span class="keyword" style="font-weight:bold">long</span> lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,                                  szKeyBuf,                                   <span class="number" style="color:rgb(0,153,153)">0</span>, NULL, REG_OPTION_NON_VOLATILE,                                  KEY_ALL_ACCESS, NULL,                                   &hKey, NULL) ;    <span class="keyword" style="font-weight:bold">if</span> (lResult != ERROR_SUCCESS)    {        <span class="keyword" style="font-weight:bold">return</span> FALSE ;    }    <span class="comment" style="color:rgb(153,153,136); font-style:italic">// Set the Value.</span>    <span class="keyword" style="font-weight:bold">if</span> (szValue != NULL)    {        RegSetValueEx(hKey, NULL, <span class="number" style="color:rgb(0,153,153)">0</span>, REG_SZ,                       (BYTE *)szValue,                       strlen(szValue)+<span class="number" style="color:rgb(0,153,153)">1</span>) ;    }    RegCloseKey(hKey) ;    <span class="keyword" style="font-weight:bold">return</span> TRUE ;}<span class="comment" style="color:rgb(153,153,136); font-style:italic"><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span>//</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// Couplet.cpp 接口的实现</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// 本文的重点,尤其是Couplet和CFactory的实现</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">//</span><span class="preprocessor" style="color:rgb(153,153,153); font-weight:bold">#include "IFace.h"</span><span class="preprocessor" style="color:rgb(153,153,153); font-weight:bold">#include "Register.h"</span><span class="preprocessor" style="color:rgb(153,153,153); font-weight:bold">#include <iostream></span><span class="keyword" style="font-weight:bold">using</span> <span class="keyword" style="font-weight:bold">namespace</span> std;<span class="comment" style="color:rgb(153,153,136); font-style:italic">// trace</span><span class="keyword" style="font-weight:bold">void</span> trace(<span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* msg) { cout<<msg<<endl; }<span class="comment" style="color:rgb(153,153,136); font-style:italic">// global variables</span>HMODULE g_hModule;<span class="keyword" style="font-weight:bold">static</span> <span class="keyword" style="font-weight:bold">long</span> g_cComponents = <span class="number" style="color:rgb(0,153,153)">0</span>;<span class="keyword" style="font-weight:bold">static</span> <span class="keyword" style="font-weight:bold">long</span> g_cLocks = <span class="number" style="color:rgb(0,153,153)">0</span>;<span class="comment" style="color:rgb(153,153,136); font-style:italic">// Friendly name of component</span><span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span> g_szFriendlyName[] = <span class="string" style="color:rgb(221,17,68)">"A Couplet"</span>;<span class="comment" style="color:rgb(153,153,136); font-style:italic">// Version independent ProgID</span><span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span> g_szVerIndProgID[] = <span class="string" style="color:rgb(221,17,68)">"Couplet.Test"</span>;<span class="comment" style="color:rgb(153,153,136); font-style:italic">// ProgID</span><span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span> g_szProgID[] = <span class="string" style="color:rgb(221,17,68)">"Couplet.Test.1"</span>;<span class="comment" style="color:rgb(153,153,136); font-style:italic">// implementation</span><span class="keyword" style="font-weight:bold">class</span> Couplet : <span class="keyword" style="font-weight:bold">public</span> ICouplet{<span class="keyword" style="font-weight:bold">public</span>:    <span class="keyword" style="font-weight:bold">virtual</span> LRESULT __stdcall QueryInterface(<span class="keyword" style="font-weight:bold">const</span> IID& iid, <span class="keyword" style="font-weight:bold">void</span>** ppv);    <span class="keyword" style="font-weight:bold">virtual</span> ULONG __stdcall AddRef()    {        <span class="keyword" style="font-weight:bold">return</span> ::InterlockedIncrement(&m_cRef);    }    <span class="keyword" style="font-weight:bold">virtual</span> ULONG __stdcall Release()    {        <span class="keyword" style="font-weight:bold">if</span>(::InterlockedDecrement(&m_cRef) == <span class="number" style="color:rgb(0,153,153)">0</span>)        {            delete <span class="keyword" style="font-weight:bold">this</span>;            <span class="keyword" style="font-weight:bold">return</span> <span class="number" style="color:rgb(0,153,153)">0</span>;        }        <span class="keyword" style="font-weight:bold">return</span> m_cRef;    }    <span class="keyword" style="font-weight:bold">virtual</span> <span class="keyword" style="font-weight:bold">void</span> what()     {         <span class="comment" style="color:rgb(153,153,136); font-style:italic">//cout<<"\n上联:我爱的人名花有主\n下联:爱我的人惨不忍睹\n横批:命苦\n\n"; </span>        cout<<<span class="string" style="color:rgb(221,17,68)">"\n1st Scroll: Study Hard, Work Hard, Make Money More and More\n\2nd Scroll: Eat Well, Sleep Well, Have Fun Day by Day\nTop Scroll: Gelievable\n\n"</span>;     }    <span class="comment" style="color:rgb(153,153,136); font-style:italic">// constructor</span>    Couplet() : m_cRef(<span class="number" style="color:rgb(0,153,153)">1</span>)     {        ::InterlockedIncrement(&g_cComponents);        trace(<span class="string" style="color:rgb(221,17,68)">"Create Couplet object"</span>);     }    <span class="comment" style="color:rgb(153,153,136); font-style:italic">// destructor</span>    ~Couplet()    {        ::InterlockedDecrement(&g_cComponents);        trace(<span class="string" style="color:rgb(221,17,68)">"Couplet object deleted"</span>);    }<span class="keyword" style="font-weight:bold">private</span>:    <span class="keyword" style="font-weight:bold">long</span> m_cRef;};<span class="comment" style="color:rgb(153,153,136); font-style:italic">// definition of QueryInterface</span>LRESULT __stdcall Couplet::QueryInterface(<span class="keyword" style="font-weight:bold">const</span> IID& iid, <span class="keyword" style="font-weight:bold">void</span>** ppv){    <span class="keyword" style="font-weight:bold">if</span>((iid == IID_IUnknown) || (iid == IID_ICouplet))    {        *ppv = static_cast<ICouplet*>(<span class="keyword" style="font-weight:bold">this</span>);    }    <span class="keyword" style="font-weight:bold">else</span>    {        *ppv = NULL;        <span class="keyword" style="font-weight:bold">return</span> E_NOINTERFACE;    }    static_cast<IUnknown*>(*ppv)->AddRef();    <span class="keyword" style="font-weight:bold">return</span> S_OK;}<span class="comment" style="color:rgb(153,153,136); font-style:italic">// class CFactory</span><span class="keyword" style="font-weight:bold">class</span> CFactory : <span class="keyword" style="font-weight:bold">public</span> IClassFactory{<span class="keyword" style="font-weight:bold">public</span>:    <span class="keyword" style="font-weight:bold">virtual</span> LRESULT __stdcall QueryInterface(<span class="keyword" style="font-weight:bold">const</span> IID& iid, <span class="keyword" style="font-weight:bold">void</span>** ppv);    <span class="keyword" style="font-weight:bold">virtual</span> ULONG __stdcall AddRef()    {        <span class="keyword" style="font-weight:bold">return</span> ::InterlockedIncrement(&m_cRef);    }    <span class="keyword" style="font-weight:bold">virtual</span> ULONG __stdcall Release()    {        <span class="keyword" style="font-weight:bold">if</span>(::InterlockedDecrement(&m_cRef) == <span class="number" style="color:rgb(0,153,153)">0</span>)        {            delete <span class="keyword" style="font-weight:bold">this</span>;            <span class="keyword" style="font-weight:bold">return</span> <span class="number" style="color:rgb(0,153,153)">0</span>;        }        <span class="keyword" style="font-weight:bold">return</span> m_cRef;    }    <span class="keyword" style="font-weight:bold">virtual</span> LRESULT __stdcall CreateInstance(IUnknown* pCmpntOuter,                                   <span class="keyword" style="font-weight:bold">const</span> IID& iid,                                   <span class="keyword" style="font-weight:bold">void</span>** ppv);    <span class="keyword" style="font-weight:bold">virtual</span> LRESULT __stdcall LockServer(BOOL bLock);<span class="keyword" style="font-weight:bold">private</span>:    <span class="keyword" style="font-weight:bold">long</span> m_cRef;};<span class="comment" style="color:rgb(153,153,136); font-style:italic">// definition of QueryInterface</span>LRESULT __stdcall CFactory::QueryInterface(<span class="keyword" style="font-weight:bold">const</span> IID& iid, <span class="keyword" style="font-weight:bold">void</span>** ppv){    <span class="keyword" style="font-weight:bold">if</span>((iid == IID_IUnknown) || (iid == IID_IClassFactory))    {        *ppv = static_cast<IClassFactory*>(<span class="keyword" style="font-weight:bold">this</span>);    }    <span class="keyword" style="font-weight:bold">else</span>    {        *ppv = NULL;        <span class="keyword" style="font-weight:bold">return</span> E_NOINTERFACE;    }    static_cast<IUnknown*>(*ppv)->AddRef();    <span class="keyword" style="font-weight:bold">return</span> S_OK;}<span class="comment" style="color:rgb(153,153,136); font-style:italic">// definition of CreateInstance</span>LRESULT __stdcall CFactory::CreateInstance(IUnknown* pCmpntOuter,                                 <span class="keyword" style="font-weight:bold">const</span> IID& iid,                                 <span class="keyword" style="font-weight:bold">void</span>** ppv){    <span class="keyword" style="font-weight:bold">if</span>(pCmpntOuter != NULL)    {        cout<<<span class="string" style="color:rgb(221,17,68)">"No Aggregate in this Class Factory"</span><<endl;        <span class="keyword" style="font-weight:bold">return</span> CLASS_E_NOAGGREGATION;    }    Couplet* pCouplet = <span class="keyword" style="font-weight:bold">new</span> Couplet;    <span class="keyword" style="font-weight:bold">if</span>(pCouplet == NULL)        <span class="keyword" style="font-weight:bold">return</span> E_OUTOFMEMORY;    HRESULT hr = pCouplet->QueryInterface(iid, ppv);    pCouplet->Release();    <span class="keyword" style="font-weight:bold">return</span> hr;}<span class="comment" style="color:rgb(153,153,136); font-style:italic">// definition of LockServer</span>LRESULT __stdcall CFactory::LockServer(BOOL bLock){    <span class="keyword" style="font-weight:bold">if</span>(bLock)    {        ::InterlockedIncrement(&g_cLocks);    }    <span class="keyword" style="font-weight:bold">else</span>    {        ::InterlockedDecrement(&g_cLocks);    }    <span class="keyword" style="font-weight:bold">return</span> S_OK;}STDAPI DllCanUnloadNow(){    <span class="keyword" style="font-weight:bold">if</span>((g_cComponents == <span class="number" style="color:rgb(0,153,153)">0</span>) && (g_cLocks == <span class="number" style="color:rgb(0,153,153)">0</span>))    {        <span class="keyword" style="font-weight:bold">return</span> S_OK;    }    <span class="keyword" style="font-weight:bold">else</span>    {        <span class="keyword" style="font-weight:bold">return</span> S_FALSE;    }}<span class="comment" style="color:rgb(153,153,136); font-style:italic">// Get class factory</span>STDAPI DllGetClassObject(<span class="keyword" style="font-weight:bold">const</span> CLSID& clsid,                         <span class="keyword" style="font-weight:bold">const</span> IID& iid,                         <span class="keyword" style="font-weight:bold">void</span>** ppv){    <span class="comment" style="color:rgb(153,153,136); font-style:italic">// Can we create this component?</span>    <span class="keyword" style="font-weight:bold">if</span>(clsid != CLSID_Couplet)    {        <span class="keyword" style="font-weight:bold">return</span> CLASS_E_CLASSNOTAVAILABLE;    }    <span class="comment" style="color:rgb(153,153,136); font-style:italic">// Create class factory</span>    CFactory* pFactory = <span class="keyword" style="font-weight:bold">new</span> CFactory;    <span class="keyword" style="font-weight:bold">if</span>(pFactory == NULL)    {        <span class="keyword" style="font-weight:bold">return</span> E_OUTOFMEMORY;    }    <span class="comment" style="color:rgb(153,153,136); font-style:italic">// Get requested interface</span>    HRESULT hr = pFactory->QueryInterface(iid, ppv);    pFactory->Release();    <span class="keyword" style="font-weight:bold">return</span> hr;}<span class="comment" style="color:rgb(153,153,136); font-style:italic">// register and unregister component</span>STDAPI DllRegisterServer(){    <span class="keyword" style="font-weight:bold">return</span> RegisterServer(g_hModule,                          CLSID_Couplet,                          g_szFriendlyName,                          g_szVerIndProgID,                          g_szProgID);}STDAPI DllUnregisterServer(){    <span class="keyword" style="font-weight:bold">return</span> UnRegisterServer(CLSID_Couplet,                            g_szVerIndProgID,                            g_szProgID);}<span class="comment" style="color:rgb(153,153,136); font-style:italic">// dll main</span>BOOL APIENTRY DllMain(HANDLE hModule,                     DWORD dwReason,                     <span class="keyword" style="font-weight:bold">void</span>* lpReserved){    <span class="keyword" style="font-weight:bold">if</span>(dwReason == DLL_PROCESS_ATTACH)    {        g_hModule = (HMODULE)hModule;    }    <span class="keyword" style="font-weight:bold">return</span> TRUE;}<span class="comment" style="color:rgb(153,153,136); font-style:italic"><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span>//</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// Couplet.def 模块定义文件</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">//</span>LIBRARY Couplet.dllEXPORTS    DllCanUnloadNow @<span class="number" style="color:rgb(0,153,153)">1</span> PRIVATE    DllGetClassObject @<span class="number" style="color:rgb(0,153,153)">2</span> PRIVATE    DllRegisterServer @<span class="number" style="color:rgb(0,153,153)">3</span> PRIVATE    DllUnregisterServer @<span class="number" style="color:rgb(0,153,153)">4</span> PRIVATE<span class="comment" style="color:rgb(153,153,136); font-style:italic"><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span><span class="xmlDocTag">///</span>//</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// Reader.cpp 通过ICouplet接口调用what()方法读取对联内容</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">// 注意: 客户端的IFace.h与COM组件中的IFace.h完全一样</span><span class="comment" style="color:rgb(153,153,136); font-style:italic">//</span><span class="preprocessor" style="color:rgb(153,153,153); font-weight:bold">#include <iostream></span><span class="preprocessor" style="color:rgb(153,153,153); font-weight:bold">#include <ObjBase.h></span><span class="preprocessor" style="color:rgb(153,153,153); font-weight:bold">#include "IFace.h"</span><span class="keyword" style="font-weight:bold">using</span> <span class="keyword" style="font-weight:bold">namespace</span> std;<span class="comment" style="color:rgb(153,153,136); font-style:italic">// global function</span><span class="keyword" style="font-weight:bold">void</span> trace(<span class="keyword" style="font-weight:bold">const</span> <span class="keyword" style="font-weight:bold">char</span>* pMsg){ cout<<pMsg<<endl; }<span class="comment" style="color:rgb(153,153,136); font-style:italic">// main function</span><span class="keyword" style="font-weight:bold">int</span> main(){    ::CoInitialize(NULL);    ICouplet* pICouplet = NULL;    HRESULT hr = ::CoCreateInstance(CLSID_Couplet, NULL, CLSCTX_INPROC_SERVER, IID_ICouplet,                                    (<span class="keyword" style="font-weight:bold">void</span>**)&pICouplet);    <span class="keyword" style="font-weight:bold">if</span>(SUCCEEDED(hr))    {        trace(<span class="string" style="color:rgb(221,17,68)">"Succeeded in getting the pointer to ICouplet"</span>);        pICouplet->what();        pICouplet->Release();    }    <span class="keyword" style="font-weight:bold">else</span>     {        trace(<span class="string" style="color:rgb(221,17,68)">"Failed to get the pointer to ICouplet"</span>);    }    ::CoUninitialize();    system(<span class="string" style="color:rgb(221,17,68)">"pause"</span>);    <span class="keyword" style="font-weight:bold">return</span> <span class="number" style="color:rgb(0,153,153)">0</span>;}
    0
    0

    我的同类文章

    http://blog.csdn.net
    • 【VS开发】关于内存泄漏的调试2016-05-07
    • 【VS开发】OutputWnd自动滚动2016-05-07
    • 【VS开发】CTimeSpan类2016-05-06
    • 【VS开发】PCIe体系结构的组成部件2016-05-05
    • 【VS开发】【DSP开发】如何使用WinDriver为PCIe采集卡装驱动2016-05-05
    • 【VS开发】内存泄漏相关问题2016-05-07
    • 【VS开发】CTime和CTimeSpan使用2016-05-06
    • 【VS开发】【电子电路技术】PCI与PCIE主板插卡与插槽识别2016-05-06
    • 【VS开发】【DSP开发】WinDriver简介(或介绍)2016-05-05
    • 【VS开发】CListBox智能滚动设置2016-05-04
    更多文章
    0 0
    原创粉丝点击