一個完整的COM 樣本Demo(C++語言描述)

來源:互聯網
上載者:User

      對於初學com的,一個完整的樣本還是挺麻煩的,最近筆者也在學習,通過自己的摸索瞭解了下基本原理。在此將一個簡單string的樣本一步一步的詳解。

     原始碼下載

1.建立工程

首先使用vs2010(筆者使用的vs2010就拿此來講)建立一個工程。選擇空項目,筆者命名為MyCom。

2.建立介面類

#ifndef IString_h__#define IString_h__#include <Windows.h>#include <Unknwn.h>#include <ObjBase.h>extern "C" const GUID IID_IString;class IString : public IUnknown{public:virtual HRESULT STDMETHODCALLTYPE SetString(char*) = 0;virtual HRESULT STDMETHODCALLTYPE GetString(char*, long) = 0;virtual HRESULT STDMETHODCALLTYPE AboutMessage() = 0;};#endif // IString_h__

3.建立組件類

#ifndef String_h__#define String_h__#include "IString.h"class String :public IString{public:String();~String();public://IUkown FunctionHRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,LPVOID *ppv);ULONG   STDMETHODCALLTYPE AddRef();ULONG   STDMETHODCALLTYPE Release();//IString FunctionHRESULT STDMETHODCALLTYPE SetString(char* chBuf);HRESULT STDMETHODCALLTYPE GetString(char* chBuf, long cLength);HRESULT STDMETHODCALLTYPE AboutMessage();protected:ULONG m_Ref;char buffer[80];};#endif // String_h__

3.定義類廠

#ifndef CFactory_h__#define CFactory_h__#include <Unknwn.h>class CFactory : public IClassFactory{public:CFactory();~CFactory();//IUnknown membersHRESULT STDMETHODCALLTYPE QueryInterface(const IID& iid, void **ppv);ULONGSTDMETHODCALLTYPE AddRef();ULONGSTDMETHODCALLTYPE Release();//IClassFactory membersHRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *, const IID& iid, void **ppv);HRESULT STDMETHODCALLTYPE LockServer(BOOL bIsLocck);protected:ULONG m_Ref;};#endif // CFactory_h__

4.類廠實現

#include "CFactory.h"#include "String.h"extern ULONG g_LockNumber;extern ULONG g_StringNumber;CFactory::CFactory(){m_Ref = 0;}CFactory::~CFactory(){}HRESULT CFactory::QueryInterface(const IID& iid, void **ppv){if (iid == IID_IUnknown){*ppv = (IUnknown*)this;((IUnknown*)(*ppv))->AddRef();}else if(iid == IID_IClassFactory){*ppv = (IClassFactory*)this;((IClassFactory*)(*ppv))->AddRef();}else{*ppv = NULL;return E_NOINTERFACE;}return S_OK;}ULONG CFactory::AddRef(){m_Ref++;return m_Ref;}ULONG CFactory::Release(){m_Ref--;if (m_Ref == 0){delete this;return 0;}return m_Ref;}HRESULT CFactory::CreateInstance(IUnknown *pUnknownOuter, const IID& iid, void **ppv){HRESULT hr;String *pObj;*ppv = NULL;hr = E_OUTOFMEMORY;if(NULL != pUnknownOuter)return CLASS_E_NOAGGREGATION;pObj = new String();if(NULL == pObj)return hr;hr = pObj->QueryInterface(iid,ppv);if (hr != S_OK){g_StringNumber--;delete pObj;}return S_OK;}HRESULT CFactory::LockServer(BOOL bIsLock){if (bIsLock)g_LockNumber++;elseg_LockNumber--;return S_OK;}

5、引出函數def檔案

LIBRARY "MyCom"EXPORTS    ; Explicit exports can go hereDllGetClassObject PRIVATEDllRegisterServer PRIVATEDllUnregisterServer PRIVATEDllCanUnloadNow  PRIVATE

6.組件註冊

#ifndef __Registry_H__#define __Registry_H__//// Registry.h//   - Helper functions registering and unregistering a component.////   - These helper functions were borrowed and modifed from//     Dale Rogerson's book Inside COM.// This function will register a component in the Registry.// DllRegisterServer function should call this function.HRESULT RegisterServer(const CLSID& clsid,                       const char *szFileName,                        const char* szProgID,                       const char* szDescription,                       const char* szVerIndProgID) ;// This function will unregister a component.  Components// DllUnregisterServer function should call this function.HRESULT UnregisterServer(const CLSID& clsid,                         const char* szProgID,                         const char* szVerIndProgID) ;#endif

7.組件註冊實現

//// Registry.cpp//#include <objbase.h>#include <assert.h>#include "Registry.h"//////////////////////////////////////////////////////////// Internal helper functions prototypes////   - These helper functions were borrowed and modifed from//     Dale Rogerson's book Inside COM.// Set the given key and its value.BOOL SetKeyAndValue(const char* pszPath,                    const char* szSubkey,                    const char* szValue) ;// Convert a CLSID into a char string.void CLSIDtoString(const CLSID& clsid,                  char* szCLSID,                 int length) ;// Delete szKeyChild and all of its descendents.LONG DeleteKey(HKEY hKeyParent, const char* szKeyString) ;//////////////////////////////////////////////////////////// Constants//// Size of a CLSID as a stringconst int CLSID_STRING_SIZE = 39 ;///////////////////////////////////////////////////////////// Public function implementation////// Register the component in the registry.//HRESULT RegisterServer(const CLSID& clsid,         // Class ID                       const char *szFileName,     // DLL module handle                       const char* szProgID,       //   IDs                       const char* szDescription,  // Description String                       const char* szVerIndProgID) // optional{    // Convert the CLSID into a char.    char szCLSID[CLSID_STRING_SIZE] ;    CLSIDtoString(clsid, szCLSID, sizeof(szCLSID)) ;    // Build the key CLSID\\{...}    char szKey[64] ;    strcpy_s(szKey, "CLSID\\") ;    strcat_s(szKey, szCLSID) ;      // Add the CLSID to the registry.    SetKeyAndValue(szKey, NULL, szDescription) ;    // Add the server filename subkey under the CLSID key.    SetKeyAndValue(szKey, "InprocServer32", szFileName) ;    // Add the ProgID subkey under the CLSID key.    if (szProgID != NULL) {        SetKeyAndValue(szKey, "ProgID", szProgID) ;        SetKeyAndValue(szProgID, "CLSID", szCLSID) ;    }    if (szVerIndProgID) {        // Add the version-independent ProgID subkey under CLSID key.        SetKeyAndValue(szKey, "VersionIndependentProgID",                       szVerIndProgID) ;        // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.        SetKeyAndValue(szVerIndProgID, NULL, szDescription) ;         SetKeyAndValue(szVerIndProgID, "CLSID", szCLSID) ;        SetKeyAndValue(szVerIndProgID, "CurVer", szProgID) ;        // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.        SetKeyAndValue(szProgID, NULL, szDescription) ;         SetKeyAndValue(szProgID, "CLSID", szCLSID) ;    }    return S_OK ;}//// Remove the component from the registry.//HRESULT UnregisterServer(const CLSID& clsid,      // Class ID                      const char* szProgID,       //   IDs                      const char* szVerIndProgID) // Programmatic{    // Convert the CLSID into a char.    char szCLSID[CLSID_STRING_SIZE] ;    CLSIDtoString(clsid, szCLSID, sizeof(szCLSID)) ;    // Build the key CLSID\\{...}    char szKey[64] ;    strcpy_s(szKey, "CLSID\\") ;    strcat_s(szKey, szCLSID) ;    // Delete the CLSID Key - CLSID\{...}    LONG lResult = DeleteKey(HKEY_CLASSES_ROOT, szKey) ;    // Delete the version-independent ProgID Key.    if (szVerIndProgID != NULL)        lResult = DeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID) ;    // Delete the ProgID key.    if (szProgID != NULL)        lResult = DeleteKey(HKEY_CLASSES_ROOT, szProgID) ;    return S_OK ;}/////////////////////////////////////////////////////////////// Internal helper functions//// Convert a CLSID to a char string.void CLSIDtoString(const CLSID& clsid,                 char* szCLSID,                 int length){    assert(length >= CLSID_STRING_SIZE) ;    // Get CLSID    LPOLESTR wszCLSID = NULL ;    HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;    assert(SUCCEEDED(hr)) ;    // Covert from wide characters to non-wide.    wcstombs(szCLSID, wszCLSID, length) ;    // Free memory.    CoTaskMemFree(wszCLSID) ;}//// Delete a key and all of its descendents.//LONG DeleteKey(HKEY hKeyParent,           // Parent of key to delete               const char* lpszKeyChild)  // Key to delete{    // Open the child.    HKEY hKeyChild ;    LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,                             KEY_ALL_ACCESS, &hKeyChild) ;    if (lRes != ERROR_SUCCESS)    {        return lRes ;    }    // Enumerate all of the decendents of this child.    FILETIME time ;    char szBuffer[256] ;    DWORD dwSize = 256 ;    while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,                        NULL, NULL, &time) == S_OK)    {        // Delete the decendents of this child.        lRes = DeleteKey(hKeyChild, szBuffer) ;        if (lRes != ERROR_SUCCESS)        {            // Cleanup before exiting.            RegCloseKey(hKeyChild) ;            return lRes;        }        dwSize = 256 ;    }    // Close the child.    RegCloseKey(hKeyChild) ;    // Delete this child.    return RegDeleteKey(hKeyParent, lpszKeyChild) ;}//// Create a key and set its value.//BOOL SetKeyAndValue(const char* szKey,                    const char* szSubkey,                    const char* szValue){    HKEY hKey;    char szKeyBuf[1024] ;    // Copy keyname into buffer.    strcpy(szKeyBuf, szKey) ;    // Add subkey name to buffer.    if (szSubkey != NULL)    {        strcat(szKeyBuf, "\\") ;        strcat(szKeyBuf, szSubkey ) ;    }    // Create and open key and subkey.    long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,                                  szKeyBuf,                                   0, NULL, REG_OPTION_NON_VOLATILE,                                  KEY_ALL_ACCESS, NULL,                                   &hKey, NULL) ;    if (lResult != ERROR_SUCCESS)    {        return FALSE ;    }    // Set the Value.    if (szValue != NULL)    {        RegSetValueEx(hKey, NULL, 0, REG_SZ,                       (BYTE *)szValue,                       strlen(szValue)+1) ;    }    RegCloseKey(hKey) ;    return TRUE ;}

8.引出函數及組件函數實現

#include "CFactory.h"#include "Registry.h"#include "String.h"ULONG g_LockNumber = 0;ULONG g_StringNumber = 0;// {913AAE18-1D57-4868-AF2F-B47D32163E8F}extern "C" const GUID CLSID_String = { 0x913aae18, 0x1d57, 0x4868, { 0xaf, 0x2f, 0xb4, 0x7d, 0x32, 0x16, 0x3e, 0x8f } };// {416DC65F-48E2-436a-BA34-FC00AC3DA598}extern "C" const GUID IID_IString = { 0x416dc65f, 0x48e2, 0x436a, { 0xba, 0x34, 0xfc, 0x0, 0xac, 0x3d, 0xa5, 0x98 } };HMODULE g_hModule=0;BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved){g_hModule = hModule;return TRUE;}extern "C" HRESULT STDMETHODCALLTYPE DllCanUnloadNow(){if((g_LockNumber == 0)&&(g_StringNumber))return S_OK;elsereturn S_FALSE;}extern "C" HRESULT STDMETHODCALLTYPE DllRegisterServer(){char szModule[1024];DWORD dwResult = ::GetModuleFileName((HMODULE)g_hModule, szModule, 1024);if (dwResult == 0)return -1;return RegisterServer(CLSID_String,szModule, "STRING.Object","MyCom String Component",NULL);}extern "C" HRESULT STDMETHODCALLTYPE DllUnregisterServer(){return UnregisterServer(CLSID_String,"STRING.Object",NULL);}extern "C" HRESULT STDMETHODCALLTYPE DllGetClassObject(__in REFCLSID rclsid, __in REFIID riid, __deref_out LPVOID FAR* ppv){if (rclsid == CLSID_String){CFactory *pFactory = new CFactory();if(pFactory == NULL)return E_OUTOFMEMORY;HRESULT hr = pFactory->QueryInterface(riid,ppv);return hr;}else{return CLASS_E_CLASSNOTAVAILABLE;}}HRESULT  String::QueryInterface(REFIID iid,LPVOID *ppv){if (iid == IID_IUnknown){*ppv = (IUnknown*)this;((IUnknown*)(*ppv))->AddRef();}else if(iid == IID_IString){*ppv = (IClassFactory*)this;((IClassFactory*)(*ppv))->AddRef();}else{*ppv = NULL;return E_NOINTERFACE;}return S_OK;}String::String(){m_Ref = 0;}String::~String(){}ULONG  String::AddRef(){m_Ref++;return m_Ref;}ULONG  String::Release(){m_Ref--;if (m_Ref == 0){delete this;return 0;}return m_Ref;}HRESULT  String::GetString(char*chBuf, long cLength){long i;  // 拷貝IExample的buffer到傳入的buffer中  i = lstrlen(buffer);  --cLength;  if (i > cLength) i = cLength;  CopyMemory(chBuf, buffer, i);  chBuf[i] = 0;  return(0); }HRESULT  String::SetString(char* chBuf){DWORD i;  // 把傳入的str拷貝到IExample的buffer中  i = lstrlen(chBuf);  if (i > 79) i = 79;  CopyMemory(buffer, chBuf, i);  buffer[i] = 0;  return(0);}HRESULT String::AboutMessage(){MessageBox(NULL,"hello, i am a message box!","Message",MB_OK);return S_OK;}

9.測試檔案編寫(記得手工註冊下dll)

#include "IString.h"#include <Windows.h>#include <iostream>using namespace std;// {913AAE18-1D57-4868-AF2F-B47D32163E8F}extern "C" const GUID CLSID_String = { 0x913aae18, 0x1d57, 0x4868, { 0xaf, 0x2f, 0xb4, 0x7d, 0x32, 0x16, 0x3e, 0x8f } };// {416DC65F-48E2-436a-BA34-FC00AC3DA598}extern "C" const GUID IID_IString = { 0x416dc65f, 0x48e2, 0x436a, { 0xba, 0x34, 0xfc, 0x0, 0xac, 0x3d, 0xa5, 0x98 } };int main(){IString *pIStr;IUnknown *pIUk = NULL;HRESULT hr;char chGetChar[80];CLSID rclsid;if(CoInitialize(NULL) != S_OK){cout<<"initialize Failed"<<endl;return -1;}hr = CLSIDFromProgID(OLESTR("STRING.Object"),&rclsid);if (hr != S_OK){cout<<"Can't find the dictionary CLSID!"<<endl;return -2;}hr = CoCreateInstance(rclsid,NULL,CLSCTX_INPROC_SERVER,IID_IUnknown,(LPVOID*)&pIUk);if (hr != S_OK){cout<<"Create object failed!"<<endl;return -2;}hr = pIUk->QueryInterface(IID_IString,(LPVOID*)&pIStr);if (hr != S_OK) {pIUk->Release();printf("QueryInterface IString failed!\n");return -3;}pIStr->SetString("wqlgregergerg");pIStr->GetString(chGetChar,sizeof(chGetChar));cout<<chGetChar<<endl;pIStr->AboutMessage();CoUninitialize();return 0;}

 終於貼完了。一個完整的樣本,親測可以哈!一起學習。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.