• vc中调用Com组件的方法详解


    引用自:http://www.cnblogs.com/jcss2008/archive/2009/10/30/1592907.html

    1.创建myCom.dll,该COM只有一个组件,两个接口IGetRes--方法Hello(),
       IGetResEx--方法HelloEx()
    2.在工程中导入组件或类型库
       #import "组件所在目录myCom.dll" no_namespace
            或
       #import "类型库所在目录myCom.tlb"
       using namespace MYCOM;

       --Method 1-------------------------------------------------------
       CoInitialize(NULL);
       CLSID clsid;
       CLSIDFromProgID(OLESTR("myCom.GetRes"),&clsid);
       CComPtr<IGetRes> pGetRes;//智能指针
       pGetRes.CoCreateInstance(clsid);
       pGetRes->Hello();
       pGetRes.Release(); //小心哦!!请看最后的“注意”
       CoUninitialize();
    --Method 2---------------------------------------------------------
       CoInitialize(NULL);
       CLSID clsid;
       HRESULT hr=CLSIDFromProgID(OLESTR("myCom.GetRes"),&clsid);
       IGetRes *ptr;
       hr=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,
                     __uuidof(IGetRes),(LPVOID*)&ptr);
       ptr->Hello();
       CoUninitialize();
    --Method 3--------------------------------------------------------
       CoInitialize(NULL);
       HRESULT hr;
       CLSID clsid;
       hr=CLSIDFromProgID(OLESTR("myCom.GetRes"),&clsid);
       IGetRes* ptr;
       IGetResEx* ptrEx;

       //使用CoCreateClassObject创建一个组件(特别是mutilThreads)的多个对象的
         时候,效率更高.
       IClassFactory* p_classfactory;
       hr=CoGetClassObject(clsid,CLSCTX_INPROC_SERVER,
                           NULL,IID_IClassFactory,
                           (LPVOID*)&p_classfactory);
       p_classfactory->CreateInstance(NULL,__uuidof(IGetRes),
                                              (LPVOID*)&ptr);
       p_classfactory->CreateInstance(NULL,__uuidof(IGetResEx),
                                              (LPVOID*)&ptrEx);
       ptr->Hello();
       ptrEx->HelloEx();
       CoUninitialize();
    --Method 4--------------------------------------------------------
        直接从dll中得到DllGetClassObject,接着生成类对象及类实例(这方法可以
    使组件不用在注册表里注册,这是最原始的方法,但这样做没什么意义,至少失去了COM
    对用户的透明性),不推荐使用.

    typedef HRESULT (__stdcall * pfnHello)(REFCLSID,REFIID,void**);
       pfnHello fnHello= NULL;
       HINSTANCE hdllInst = LoadLibrary("组件所在目录myCom.dll");
       fnHello=(pfnHello)GetProcAddress(hdllInst,"DllGetClassObject");
       if (fnHello != 0)
       {
       IClassFactory* pcf = NULL;
       HRESULT hr=(fnHello)(CLSID_GetRes,IID_IClassFactory,(void**)&pcf);
       if (SUCCEEDED(hr) && (pcf != NULL))
       {
       IGetRes* pGetRes = NULL;
       hr = pcf->CreateInstance(NULL, IID_IFoo, (void**)&pGetRes);
       if (SUCCEEDED(hr)   && (pFoo != NULL))
       {
       pGetRes->Hello();
       pGetRes->Release();
       }
       pcf->Release();
       }
       }
       FreeLibrary(hdllInst);
    --Method 5-------------------------------------------------------
        通过ClassWizard利用类型库生成包装类,不过前提是com组件的接口必须是派
    生自IDispatch,具体方法:
        调出添加类向导(.NET中),选择类型库中MFC类,打开,选择"文件",选择
    "myCom.dll"或"myCom.tlb",接下来会出来该myCom中的所有接口,选择你想
    生成的接口包装类后,向导会自动生成相应的.h文件.这样你就可以在你的MFC中
    像使用普通类那样使用组件了.(CreateDispatch("myCom.GetRes") 中的参数就是ProgID通过Clsid在注册表中可以查询的到)

       CoInitialize(NULL);
       CGetRes getRest;
       if (getRest.CreateDispatch("myCom.GetRes") != 0)
       {
       getRest.Hello();
       getRest.ReleaseDispatch();
       }
       CoUninitialize();
    --注意--------------------------------------------------------------
         COM中的智能指针实际上是重载了->的类,目的是为了简化引用记数,不需要程序
    员显示的调用AddRef()和Release(),但是为什么我们在Method 1中
    pGetRes.Release(),问题在与,我们的智能指针pGetRes生命周期的结束是在
    CoUninitialize()之后,CoInitialize所开的套间在CoUninitialize()后已经被
    关闭,而pGetRes此时发生析构,导致了程序的崩溃,解决这个问题的另一个方法是
       CoInitialize(NULL);
       CLSID clsid;
       CLSIDFromProgID(OLESTR("myCom.GetRes"),&clsid);
       {
       CComPtr<IGetRes> pGetRes;//智能指针
       pGetRes.CoCreateInstance(clsid);
       pGetRes->Hello();
       }
       CoUninitialize();

    二。----------------------------------------------------------------------------------------

    准备及条件:  
      COM服务器为进程内服务器,DLL名为simpCOM.dll,该组件只有一个接口IFoo,该接口只有一个方法HRESULT   SayHello(void)  
       
       
      在SDK中调用  
      =====================================  
      一、最简单最常用的一种,用#import导入类型库,利用VC提供的智能指针包装类  
      演示代码:  
       
      #import   "D:\Temp\vc\simpCOM\Debug\simpCOM.dll"   no_namespace  
      CoInitialize(NULL);  
       
      IFooPtr   spFoo   =   NULL;  
      spFoo.CreateInstance(__uuidof(Foo));  
      spFoo->SayHello();  
      spFoo.Release();/*晕死了,本来智能指针就是为了让用户不用关心这个的,可是我发现如果不手工调用一下的话,程序退出后会发生内存访问错误,我是在console中做试验的,哪位大侠知道怎么回事请一定指教*/  
      CoUninitialize();  
       
       
       
      二、引入midl.exe产生的*.h,*_i.c文件,利用CoCreateInstance函数来调用  
       
      演示代码:  
      /*在工程中加入*_i.c文件,例如本例的simpCOM_i.c,该文件定义了类和接口的guid值,如果不引入的话,会发生连接错误。*/  
       
      #include   "D:\Temp\vc\simpCOM\simpCOM.h"  
      CoInitialize(NULL);  
       
      IFoo*   pFoo   =   NULL;  
      HRESULT   hr   =   CoCreateInstance(CLSID_Foo,   NULL,   CLSCTX_ALL,   IID_IFoo,   (void**)&pFoo);  
      if   (SUCCEEDED(hr)   &&   (pFoo   !=   NULL))  
      {  
      pFoo->SayHello();  
      pFoo->Release();  
      }  
       
      CoUninitialize();  
       
      三、不用CoCreateInstance,直接用CoGetClassObejct得到类厂对象接口,然后用该接口的方法CreateInstance来生成实例。  
      演示代码:  
      /*前期准备如二方法所述*/  
      IClassFactory*   pcf   =   NULL;  
      HRESULT hr   =   CoGetClassObject(CLSID_Foo,   CLSCTX_ALL,   NULL,   IID_IClassFactory,   (void**)&pcf);  
      if   (SUCCEEDED(hr)   &&   (pcf   !=   NULL))  
      {  
      IFoo*   pFoo   =   NULL;  
      hr   =   pcf->CreateInstance(NULL,   IID_IFoo,   (void**)&pFoo);  
      if   (SUCCEEDED(hr)     &&   (pFoo   !=   NULL))  
      {  
      pFoo->SayHello();  
      pFoo->Release();  
      }  
      pcf->Release();  
      }  
       
       
       
      四、不用CoCreateInstance   or   CoGetClassObject,直接从dll中得到DllGetClassObject,接着生成类对象及类实例(本方法适合于你想用某个组件,却不想在注册表中注册该组件)  
       
      演示代码:  
      /*前期准备工作如二方法所述,事实上只要得到CLSID和IID的定义及接口的定义就行*/  
       
      typedef   HRESULT   (__stdcall   *   pfnGCO)   (REFCLSID,   REFIID,   void**);  
      pfnGCO   fnGCO   =   NULL;  
      HINSTANCE   hdllInst   =   LoadLibrary("D:\\Temp\\vc\\simpCOM\\Debug\\simpCOM.dll");  
      fnGCO   =   (pfnGCO)GetProcAddress(hdllInst,   "DllGetClassObject");  
      if   (fnGCO   !=   0)  
      {  
      IClassFactory*   pcf   =   NULL;  
      HRESULT   hr=(fnGCO)(CLSID_Foo,   IID_IClassFactory,   (void**)&pcf);  
      if   (SUCCEEDED(hr)   &&   (pcf   !=   NULL))  
      {  
      IFoo*   pFoo   =   NULL;  
      hr   =   pcf->CreateInstance(NULL,   IID_IFoo,   (void**)&pFoo);  
      if   (SUCCEEDED(hr)     &&   (pFoo   !=   NULL))  
      {  
      pFoo->SayHello();  
      pFoo->Release();  
      }  
      pcf->Release();  
      }  
      }  
      FreeLibrary(hdllInst);  
       
       
      在MFC中调用  
      =====================================  
      在MFC中除了上面的几种方法外,还有一种更方便的方法,就是通过ClassWizard利用类型库生成包装类,不过有个前提就是com组件的接口必须是派生自IDispatch  
       
      具体方法:  
      1、按Ctrl+W调出类向导,按Add   Class按钮弹出新菜单,选From   a   type   libarary,然后定位到simpCOM.dll,接下来会出来该simpCOM中的所有接口,选择你想生成的接口包装类后,向导会自动生成相应的.cpp和.h文件.  
      这样你就可以在你的MFC工程中像使用普通类那样使用COM组件了.  
       
      演示代码:  
       
      CoInitialize(NULL);  
       
      IFoo   foo;  
      if   (foo.CreateDispatch("simpCOM.Foo")   !=   0)  
      {  
      foo.SayHello();  
      foo.ReleaseDispatch();  
      }  
       
      CoUninitialize();

  • 相关阅读:
    关于字段长度的定义
    连续滚动效果的脚本
    JavaScript显示日期,跳动时间,星期
    [转载]SQL2000里的数据类型
    VSTSTF54000错误
    Delphi TreeView 现场保存与恢复
    易简协同平台与佛道修行
    CMD 反编译CHM文件
    专家与大师
    流程建模思考(草)
  • 原文地址:https://www.cnblogs.com/fwycmengsoft/p/2995524.html
Copyright © 2020-2023  润新知