CoGetClassObject()
我有点问题。
我有一个必须使用特定版本的DLL的应用程序, 但它们也存在于系统中,在更新的版本中。
所以我开始挂钩CoCreateInstance()
和loadLibrary()
,我觉得这很好。
问题是两个版本中的DLL都已加载。
所以我认为CoGetClassObject()
是问题/解决方案,因为它提供了指向与包含应用程序必须在旧版本中使用的DLL的CLSID关联的对象的接口的指针。
但我不知道这个功能“做什么”,那么如何“覆盖”这个功能呢?
感谢。
PS:我是COM编程的新手。
答案 0 :(得分:4)
CoGetClassObject()只执行CoCreateInstance()所做工作的一半。它返回一个类工厂。然后CoCreateInstance()调用IClassFactory :: CreateInstance()并释放IClassFactory。如果您需要创建某个coclass的许多对象并希望对其进行优化,则只能使用它。它避免了一次又一次地创建和发布工厂的成本。
您可能忽略了解决此问题的简单方法。您只需将新版本的COM服务器DLL复制到与客户端EXE相同的目录中即可。并创建一个名为“app.exe.local”的零字节文件,其中“app”是EXE的名称。这足以强制加载复制的DLL而不是注册表指向的DLL。 MSDN Library有关DLL重定向的文章is here。
答案 1 :(得分:0)
非常简单的解释是CoGetClassObject()
打开HKCR\CLSID\{ClassId}
并查看InProcServer32
或LocalServer32
,具体取决于传递的CLSCTX_*
值 - 即COM服务器路径。
一旦发现COM服务器文件路径被加载(LoadLibraryEx()
在进程中为LOAD_WITH_ALTERED_SEARCH_PATH
标志,或在出...的情况下为CreateProcess()
)COM服务器。然后它为进程内服务器找到并调用DllGetClassObject()
或等待直到为out-proc服务器注册类工厂。
这当然忽略了DCOM等内容。您可以使用Process Monitor实用程序更好地了解它如何遍历注册表。
答案 2 :(得分:0)
如果要加载特定的COM DLL,无论是否安装了较新的版本,并且无论旧版DLL位于何处,都只需完全忽略CoCreateInstance()
和CoGetClassObject()
。通过LoadLibrary()
自行加载旧DLL,然后直接调用其导出的DllGetClassObject()
函数以获取DLL的IClassFactory
接口,然后根据需要调用IClassFactory::CreateInstance()
。无论如何,这都是CoCreateInstance()
和CoGetClassObject()
内部执行,但这会绕过他们执行的注册表查找,以确定要加载的DLL路径。