Visual C++ 7.1Visual C++ 8.0COMVisual C++ 7.0Windows 2003Windows 2000Visual C++ 6.0Windows XP中级开发Visual StudioWindowsC++
模拟 CoCreateInstance()






4.77/5 (27投票s)
2007年4月17日
1分钟阅读

110255
描述如何在无需注册的情况下使用 COM 对象。
引言
不久前,我编写了一个小型实用工具,它使用 WinGraphViz.DLL COM 组件将 DOT 语法转换为图像。
然而,在运行该工具之前,让用户注册此组件并不常见,因此我开始寻找一种将 COM 组件像普通 DLL 一样使用的方法。研究表明,有很多技术可以实现这一点。
- 无注册 COM (适用于 XP 及更高版本)
- 模拟
CoCreateInstance()
要了解有关无注册 COM 的更多信息,请查看本文末尾的参考资料。
模拟 CoCreateInstance()
通常,要创建一个实例,你会执行类似的操作
hr = CoCreateInstance(CLSID_DOT, NULL, CLSCTX_ALL, IID_IDOT, (LPVOID *)&pIDOT);
这将导致 OLE 从注册表中获取关联的 DLL,并调用其 DllGetClassObject()
方法来获取类工厂,然后从类工厂创建所需 IID 的实例。
因此,我们可以通过以下代码模拟 CoCreateInstance()
HRESULT __stdcall MyCoCreateInstance( LPCTSTR szDllName, IN REFCLSID rclsid, IUnknown* pUnkOuter, IN REFIID riid, OUT LPVOID FAR* ppv) { HRESULT hr = REGDB_E_KEYMISSING; HMODULE hDll = ::LoadLibrary(szDllName); if (hDll == 0) return hr; typedef HRESULT (__stdcall *pDllGetClassObject)(IN REFCLSID rclsid, IN REFIID riid, OUT LPVOID FAR* ppv); pDllGetClassObject GetClassObject = (pDllGetClassObject)::GetProcAddress(hDll, "DllGetClassObject"); if (GetClassObject == 0) { ::FreeLibrary(hDll); return hr; } IClassFactory *pIFactory; hr = GetClassObject(rclsid, IID_IClassFactory, (LPVOID *)&pIFactory); if (!SUCCEEDED(hr)) return hr; hr = pIFactory->CreateInstance(pUnkOuter, riid, ppv); pIFactory->Release(); return hr; }
请注意,此函数接受一个参数,该参数包含 DLL 的名称。
使用代码
如果 COM 已注册,则你的应用程序需要首先运行,否则你将诉诸模拟 CoCreateInstance()
。你的代码可能如下所示
hr = CoCreateInstance(CLSID_DOT, NULL, CLSCTX_ALL, IID_IDOT, (LPVOID *)&pIDOT); if (hr == REGDB_E_CLASSNOTREG) { hr = MyCoCreateInstance(_T("WinGraphViz.dll"), CLSID_DOT, NULL, IID_IDOT, (LPVOID *)&pIDOT); } if (FAILED(hr)) { cout << "CoCreateInstance Failed: " << hr << "nn"; return -1; }
参考
以下链接在构建这个简单的代码片段时很有帮助