天天看點

COM建立對象方法

軟體架構師何志丹

1、建立COM元件的架構。(元件已注冊)

IUnknown *pUnk = NULL;
IObject *pObject = NULL;
CoInitialize(NULL);
CoCreateInstance(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IDD_Unknown, (void**)&pUnk);
pUnk->QueryInterface(IID_IObject, (void**)&pObject);
pUnk->Release();
pObject->Func();
pObject->Release();
 CoUninitialize();
CoCreateInstance的内部:
CoCreateInstance(....)
 {
   .......
   IClassFactory *pClassFactory=NULL;   //先獲得類工廠對象①
   CoGetClassObject(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void **)&pClassFactory);   //再通過類工廠對象建立元件并且得到IUnknown指針。②
   pClassFactory->CreateInstance(NULL, IID_IUnknown, (void**)&pUnk);
   pClassFactory->Release();
   ........
 }
//①-------------------
CoGetClassObject的内部:
CoGetClassObject(.....)
 {
   //通過查系統資料庫CLSID_Object,得知元件DLL的位置、檔案名
   //使用LoadLibrary裝入DLL庫
   //使用函數GetProcAddress( "DllGetClassObject" )得到DLL庫中函數DllGetClassObject的函數指針。
   //調用DllGetClassObject
 }DllGetClassObject是用來獲得類工廠對象的,隻有先得到類工廠才能去建立元件。
DllGetClassObject代碼:
 HRESULT_export  PASCAL DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID * ppvObj)
 {
     HRESULT hr = E_OUTOFMEMORY;
     *ppvObj = NULL;

     CClassFactory *pClassFactory = new CClassFactory(rclsid); //類工廠
     if (pClassFactory != NULL)   {
         hr = pClassFactory->QueryInterface(riid, ppvObj);
         pClassFactory->Release();
     }
     return hr;
 }//②----------------
CFactory::CreateInstance(.....)
 {
   ...........
   CObject *pObject = new CObject; //元件對象
   pObject->QueryInterface(IID_IUnknown, (void**)&pUnk);
   pObject->Release();
   ...........
 }      

執行個體:

CComPtr<IAVIer> m_piAVIer;
m_piAVIer.CoCreateInstance(L"AVI.AVIer");      

2、通過LoadLibrary和DllGetClassObject建立元件對象(元件未注冊)

CComPtr<IAVIer> m_piAVIer;
typedef int (WINAPI *DllGetClassObjectPtr)(REFCLSID, REFIID, LPVOID*);
HMODULE hModule = LoadLibrary(dll檔案路徑);
//得到DllGetClassObject函數位址
DllGetClassObjectPtr ProcPtr = (DllGetClassObjectPtr)GetProcAddress(hModule, "DllGetClassObject");
CLSID rclsid;
 IID riid;
 ::CLSIDFromString(A2W("{D5A365A3-44F8-47A0-8FCF-062372B1EB83}"), &rclsid);//類ID
 ::IIDFromString(A2W("{BE136856-CBEA-4079-A02B-BBC7A382BDB3}"), &riid);//接口IDIClassFactory *pICF = NULL;//類工廠接口指針
ProcPtr(rclsid, IID_IClassFactory, (void**)(&pICF));//擷取類工廠接口指針
//以上相當于①
pICF->CreateInstance(NULL, riid, (void**)&m_piAVIer);//建立COM對象
//以上相當于②
pICF->Release();      

備注:

HKCR
 {
  Avi.AVIer.1 = s 'AVIer Class'
  {
   CLSID = s '{D5A365A3-44F8-47A0-8FCF-062372B1EB83}'
  }
  Avi.AVIer = s 'AVIer Class'
  {
   CLSID = s '{D5A365A3-44F8-47A0-8FCF-062372B1EB83}'
   CurVer = s 'Avi.AVIer.1'
  }
  NoRemove CLSID
  {
   ForceRemove {D5A365A3-44F8-47A0-8FCF-062372B1EB83} = s 'AVIer Class'
   {
    ProgID = s 'Avi.AVIer.1'
    VersionIndependentProgID = s 'Avi.AVIer'
    ForceRemove 'Programmable'
    InprocServer32 = s '%MODULE%'
    {
     val ThreadingModel = s 'Both'
    }
    'TypeLib' = s '{59AE79C3-3AC6-42E1-ABED-10B363EDAA4C}'
   }
  }
 }      
[
   object,
   uuid(BE136856-CBEA-4079-A02B-BBC7A382BDB3),//接口ID
   dual,
   helpstring("IAVIer Interface"),
   pointer_default(unique)
  ]
library AVILib
 {
  importlib("stdole32.tlb");
  importlib("stdole2.tlb");[
   uuid(D5A365A3-44F8-47A0-8FCF-062372B1EB83),//類ID
   helpstring("AVIer Class")
  ]
  coclass AVIer
  {
   [default] interface IAVIer;//類ID

  };
 };