描述:
作者联系方式:
email: libodeng@gmail.com
msn: libodeng@gmail.com
更多文章请访问本人blog http://libo.deng.blog.163.com
引子
对于包含大量COM组件的程序,在处理版本变更,升级,卸载时往往容易遇到各种各样的问题,这里基于ATL给出了一种在内存中直接加载COM的实现,这种方式不需要组件预先在操作系统进行注册(即载即用),特别适合那些需要直接动态创建COM的场合。
实现
对ATL组件端,需要提供一个动态创建的入口函数,实际上只需要增加一小行代码,然后把COM创建过程直接委托给ATL实现:
//直接创建入口点
STDAPI DllCreateObject(REFIID riid, LPVOID* ppv)
{
CComPtr<IClassFactory> pFactory;
HRESULT hr = _Module.GetClassObject(CLSID_Control/*你的组件CLSID*/, IID_IClassFactory, (void**)&pFactory);
if (hr == S_OK)
hr = pFactory->CreateInstance(0, riid, ppv);
return hr;
}
如果有必要,你也可以去掉四个标准导出函数
STDAPI DllCanUnloadNow(void)
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
STDAPI DllRegisterServer(void)
STDAPI DllUnregisterServer(void)
在COM调用端,只要装载包含COM的DLL,调用刚才增加的入口函数即可
typedef HRESULT (WINAPI* DLLCREATEOBJECTFUNC) (REFIID riid, LPVOID* ppv);
CreateComObject(LPCTSTR lpszModuleFile, const IID &riid, void **ppv)
{
*ppv = NULL;
HMODULE hDLL = LoadLibrary(lpszModuleFile);
TCHAR msg[512];
if (hDLL == NULL)
{
wsprintf(msg, _T("未找到动态链接库文件:%s!请确认该文件已经存在!"),lpszModuleFile);
::MessageBox(NULL, msg, _T("Error"), MB_OK | MB_ICONERROR);
return;
}
DLLCREATEOBJECTFUNC pFunc = (DLLCREATEOBJECTFUNC)GetProcAddress(hDLL, "DllCreateObject");
if (pFunc == NULL)
{
wsprintf(msg, _T("在库文件%s中未找到入口函数 DllCreateObject!"),lpszModuleFile);
::MessageBox(NULL, msg, _T("Error"), MB_OK | MB_ICONERROR);
FreeLibrary(hDLL);
return;
}
HRESULT hr = (*pFunc)(riid, ppv);
if (hr != S_OK || *ppv == NULL)
{
FreeLibrary(hDLL);
wsprintf(msg, _T("调用DllCreateObject创建对象错误! (%s)"),lpszModuleFile);
::MessageBox(NULL, msg, _T("Error"), MB_OK | MB_ICONERROR);
}
}
欢迎访问全球最不受欢迎的技术blog
http://libo.deng.blog.163.com