手工加载未注册的 COM 组件

手工加载未注册的 COM 组件


http://www.cppblog.com/sleepwom/archive/2010/02/16/107921.html


二 14, 2010

有时候我们运行程序的时候, 可能某个组件在系统内并不存在, 所以我们自己将这个组件打包在我们的安装包内, 但并不将其注册进系统. 这样做的目的就是尽量少的影响原有的系统. 组件只是在我们的应用程序需要的时候才加载进去. 不用的时候将其卸载.

用这种途径创建组件实例的主要思路就是, 调用组件 DLL 导出的 DllGetClassObject 函数, 创建类厂 IClassFactory 的实例, 然后用 IClassFactory::CreateInstance 函数创建目标接口指针的实例.

以下是用法:

1. 将某个组件加载进程序

1TCHARszXmlPath[MAX_PATH] = { 0 };
2GetModuleFileName(NULL, szXmlPath, _countof(szXmlPath));
3PathRemoveFileSpec(szXmlPath);
4PathAppend(szXmlPath, _T("msxml4.dll"));
5TinyInitComLibrary(szXmlPath, __uuidof(DOMDocument40));

2. 使用组件

1CComPtr<IXMLDOMDocument2> spXMLDoc;
2hr = spXMLDoc.CoCreateInstance(__uuidof(DOMDocument40));
3if(FAILED(hr)) {
4    hr = TinyCoCreateInstance(__uuidof(DOMDocument40), NULL, CLSCTX_ALL,
5        __uuidof(IXMLDOMDocument2), (void**)&spXMLDoc);
6    if(FAILED(hr)) {
7        returnE_FAIL
8    }
9}

3. 将所有强制加载的组件卸载

1TinyReleaseAllComLibrary();


以下是实现的源代码:

001#ifndef __TINY_CREATE_COM_OBJ_H__
002#define __TINY_CREATE_COM_OBJ_H__   1
003  
004typedefHRESULT(WINAPI * PFN_DllCanUnloadNow)(void);
005typedefHRESULT(WINAPI * PFN_DllGetClassObject)(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
006  
007#include <vector>
008#include <algorithm>
009  
010typedefstructCOM_OBJ_DLL_CONTAINER
011{
012    HINSTANCEhDllInst;
013    CLSID clsObject;
014} COM_OBJ_DLL_CONTAINER ;
015  
016typedefstd::vector<COM_OBJ_DLL_CONTAINER> COM_LIB_ARR_TYPE;
017  
018__declspec(selectany) COM_LIB_ARR_TYPE * g_vecComLib = NULL;
019  
020__inline HRESULTWINAPI TinyInitComLibrary(LPCTSTRlpszObjHostPath, REFCLSID rclsid)
021{
022    if(NULL == g_vecComLib) {
023        g_vecComLib = newCOM_LIB_ARR_TYPE();
024    }
025  
026    HRESULThr = E_FAIL;
027    COM_OBJ_DLL_CONTAINER tmp = { 0 };
028    tmp.hDllInst = LoadLibrary(lpszObjHostPath);
029    if(tmp.hDllInst)
030    {
031        tmp.clsObject = rclsid;
032        g_vecComLib->push_back(tmp);
033        hr = S_OK;
034    }
035    returnhr;
036}
037  
038__inline HRESULTWINAPI TinyReleaseComLibrary(REFCLSID rclsid)
039{
040    HRESULThr = E_FAIL;
041    if(NULL == g_vecComLib) {
042        returnhr;
043    }
044  
045    COM_LIB_ARR_TYPE::iterator it;
046    for(it=g_vecComLib->begin(); it!=g_vecComLib->end(); it++)
047    {
048        if(IsEqualCLSID(it->clsObject, rclsid))
049        {
050            BOOLbCanUnload = TRUE;
051            PFN_DllCanUnloadNow pfn_DllCanUnloadNow = NULL;
052            pfn_DllCanUnloadNow = (PFN_DllCanUnloadNow) GetProcAddress(it->hDllInst, "DllCanUnloadNow");
053            if(pfn_DllCanUnloadNow && S_OK != pfn_DllCanUnloadNow()) {
054                bCanUnload = FALSE;
055            }
056  
057            if(bCanUnload) {
058                FreeLibrary(it->hDllInst);
059                g_vecComLib->erase(it);
060                hr = S_OK;
061            }
062            break;
063        }
064    }
065  
066    if(0 == g_vecComLib->size()) {
067        deleteg_vecComLib;
068        g_vecComLib = NULL;
069    }
070  
071    returnhr;
072}
073  
074__inline HRESULTWINAPI TinyReleaseAllComLibrary(void)
075{
076    HRESULThr = S_OK;
077    if(NULL == g_vecComLib) {
078        returnhr;
079    }
080  
081    COM_LIB_ARR_TYPE::iterator it;
082    for(it=g_vecComLib->begin(); it!=g_vecComLib->end(); it++)
083    {
084        FreeLibrary(it->hDllInst);
085    }
086    g_vecComLib->clear();
087    deleteg_vecComLib;
088    g_vecComLib = NULL;
089    returnhr;
090}
091  
092__inline HRESULTWINAPI TinyCoCreateInstance(IN REFCLSID rclsid, IN LPUNKNOWN pUnkOuter,
093                                          IN DWORDdwClsContext, IN REFIID riid, OUT LPVOIDFAR* ppv)
094{
095    HRESULThr = E_FAIL;
096  
097    if(g_vecComLib==NULL)
098    {
099        __asm int3;
100        returnhr;
101    }
102  
103    COM_LIB_ARR_TYPE::iterator it;
104  
105    for(it=g_vecComLib->begin(); it!=g_vecComLib->end(); it++)
106    {
107        if(IsEqualCLSID(it->clsObject, rclsid))
108        {
109            PFN_DllGetClassObject pfn_DllGetClassObject = NULL;
110            pfn_DllGetClassObject = (PFN_DllGetClassObject) GetProcAddress(it->hDllInst, "DllGetClassObject");
111            if(pfn_DllGetClassObject) {
112                CComQIPtr<IClassFactory> spClsFact;
113                hr = pfn_DllGetClassObject(rclsid, __uuidof(IClassFactory), (void**)&spClsFact);
114                if(SUCCEEDED(hr))
115                {
116                    hr = spClsFact->CreateInstance(NULL, riid, ppv);
117                }
118            }
119            break;
120        }
121    }
122    returnhr;
123}
124  
125#endif  // __TINY_CREATE_COM_OBJ_H__
by free2000fly | Categories: 技术心得 | Tagged: |

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值