Posted on 2010-02-16 15:43
S.l.e!ep.¢% 閱讀(1432)
評論(0) 編輯 收藏 引用 所屬分類:
COM
手工加載未注冊的 COM 組件
二 14, 2010
有時候我們運行程序的時候, 可能某個組件在系統內并不存在, 所以我們自己將這個組件打包在我們的安裝包內, 但并不將其注冊進系統. 這樣做的目的就是盡量少的影響原有的系統. 組件只是在我們的應用程序需要的時候才加載進去. 不用的時候將其卸載.
用這種途徑創建組件實例的主要思路就是, 調用組件 DLL 導出的 DllGetClassObject 函數, 創建類廠 IClassFactory 的實例, 然后用 IClassFactory::CreateInstance 函數創建目標接口指針的實例.
以下是用法:
1. 將某個組件加載進程序
1
|
TCHAR
szXmlPath[MAX_PATH] = { 0 };
|
2
|
GetModuleFileName(NULL, szXmlPath, _countof(szXmlPath));
|
3
|
PathRemoveFileSpec(szXmlPath);
|
4
|
PathAppend(szXmlPath, _T(
"msxml4.dll"
));
|
5
|
TinyInitComLibrary(szXmlPath, __uuidof(DOMDocument40));
|
2. 使用組件
1
|
CComPtr<IXMLDOMDocument2> spXMLDoc;
|
2
|
hr = spXMLDoc.CoCreateInstance(__uuidof(DOMDocument40));
|
4
|
????
hr = TinyCoCreateInstance(__uuidof(DOMDocument40), NULL, CLSCTX_ALL,
|
5
|
????????
__uuidof(IXMLDOMDocument2), (
void
**)&spXMLDoc);
|
3. 將所有強制加載的組件卸載
1
|
TinyReleaseAllComLibrary();
|
以下是實現的源代碼:
001
|
#ifndef __TINY_CREATE_COM_OBJ_H__
|
002
|
#define __TINY_CREATE_COM_OBJ_H__?? 1
|
004
|
typedef
HRESULT
(WINAPI * PFN_DllCanUnloadNow)(
void
);
|
005
|
typedef
HRESULT
(WINAPI * PFN_DllGetClassObject)(REFCLSID rclsid, REFIID riid,
LPVOID
* ppv);
|
010
|
typedef
struct
COM_OBJ_DLL_CONTAINER
|
012
|
????
HINSTANCE
hDllInst;
|
013
|
????
CLSID clsObject;
|
014
|
} COM_OBJ_DLL_CONTAINER ;
|
016
|
typedef
std::vector<COM_OBJ_DLL_CONTAINER> COM_LIB_ARR_TYPE;
|
018
|
__declspec
(
selectany
) COM_LIB_ARR_TYPE * g_vecComLib = NULL;
|
020
|
__inline
HRESULT
WINAPI TinyInitComLibrary(
LPCTSTR
lpszObjHostPath, REFCLSID rclsid)
|
022
|
????
if
(NULL == g_vecComLib) {
|
023
|
????????
g_vecComLib =
new
COM_LIB_ARR_TYPE();
|
026
|
????
HRESULT
hr = E_FAIL;
|
027
|
????
COM_OBJ_DLL_CONTAINER tmp = { 0 };
|
028
|
????
tmp.hDllInst = LoadLibrary(lpszObjHostPath);
|
029
|
????
if
(tmp.hDllInst)
|
031
|
????????
tmp.clsObject = rclsid;
|
032
|
????????
g_vecComLib->push_back(tmp);
|
038
|
__inline
HRESULT
WINAPI TinyReleaseComLibrary(REFCLSID rclsid)
|
040
|
????
HRESULT
hr = E_FAIL;
|
041
|
????
if
(NULL == g_vecComLib) {
|
045
|
????
COM_LIB_ARR_TYPE::iterator it;
|
046
|
????
for
(it=g_vecComLib->begin(); it!=g_vecComLib->end(); it++)
|
048
|
????????
if
(IsEqualCLSID(it->clsObject, rclsid))
|
050
|
????????????
BOOL
bCanUnload = 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;
|
057
|
????????????
if
(bCanUnload) {
|
058
|
????????????????
FreeLibrary(it->hDllInst);
|
059
|
????????????????
g_vecComLib->erase(it);
|
060
|
????????????????
hr = S_OK;
|
066
|
????
if
(0 == g_vecComLib->size()) {
|
067
|
????????
delete
g_vecComLib;
|
068
|
????????
g_vecComLib = NULL;
|
074
|
__inline
HRESULT
WINAPI TinyReleaseAllComLibrary(
void
)
|
076
|
????
HRESULT
hr = S_OK;
|
077
|
????
if
(NULL == g_vecComLib) {
|
081
|
????
COM_LIB_ARR_TYPE::iterator it;
|
082
|
????
for
(it=g_vecComLib->begin(); it!=g_vecComLib->end(); it++)
|
084
|
????????
FreeLibrary(it->hDllInst);
|
086
|
????
g_vecComLib->clear();
|
087
|
????
delete
g_vecComLib;
|
088
|
????
g_vecComLib = NULL;
|
092
|
__inline
HRESULT
WINAPI TinyCoCreateInstance(IN REFCLSID rclsid, IN LPUNKNOWN pUnkOuter,
|
093
|
??????????????????????????????????????????
IN
DWORD
dwClsContext, IN REFIID riid, OUT
LPVOID
FAR* ppv)
|
095
|
????
HRESULT
hr = E_FAIL;
|
097
|
????
if
(g_vecComLib==NULL)
|
099
|
????????
__asm
int
3;
|
103
|
????
COM_LIB_ARR_TYPE::iterator it;
|
105
|
????
for
(it=g_vecComLib->begin(); it!=g_vecComLib->end(); it++)
|
107
|
????????
if
(IsEqualCLSID(it->clsObject, rclsid))
|
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))
|
116
|
????????????????????
hr = spClsFact->CreateInstance(NULL, riid, ppv);
|
125
|
#endif? // __TINY_CREATE_COM_OBJ_H__
|
by
free2000fly | Categories:
技術心得 | Tagged:
加載 COM 組件 |