我在 python.h rel = nofollow noreferrer> Visual C ++ DLL文件项目,导致与 python25.dll 的隐式链接。但是,我想加载一个特定的 python25.dll (几个可以存在于计算机上),所以我创建了一个非常简单的清单文件,名为 test.manifest :
I'm including python.h in my Visual C++ DLL file project which causes an implicit linking with python25.dll. However, I want to load a specific python25.dll (several can be present on the computer), so I created a very simple manifest file named test.manifest:
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'> <file name="python25.dll" /> </assembly>我将它与Visual Studio生成的自动嵌入的清单文件合并,感谢: p>
And I'm merging it with the automatically embedded manifest file generated by Visual Studio thanks to:
Configuration Properties -> Manifest Tool -> Input and Output -> Additional Manifest Files -->$(ProjectDir)\src\test.manifestpython25.dll 现在加载了两次:清单请求的一个,Windows将通过搜索顺序找到它。
python25.dll is now loaded twice: the one requested by the manifest, and the one that Windows should find through its search order.
Process Explorer的Screendump dl.dropbox /u/3545118/python25_dll.png
为什么会发生这种情况,如何加载清单指向的DLL文件?
Why is that happening and how can I just load the DLL file pointed by the manifest?
推荐答案在与 WinSxS 和DLL重定向,这是我的建议:
After exhaustive battle with WinSxS and DLL redirection, here's my advice for you:
各种事情都可能导致在Windows下加载一个DLL文件:
Various things can cause a DLL file to be loaded under Windows:
- 显式链接(的LoadLibrary ) - 加载程序使用正在运行的EXE文件的当前激活上下文。这是直观的。
- 隐式链接(加载时间链接,自动链接) - 加载程序使用 >依赖DLL文件。如果 A.exe 取决于 B.dll 取决于 C.dll (所有隐式链接),加载程序将在加载 C.dll 。 IIRC,这意味着如果B的 DllMain 加载 C.dll ,它可以使用 B。 dll 的激活上下文 - 大部分时间表示系统范围的默认激活上下文。所以你从%SystemRoot%中获取你的Python DLL。
- COM( CoCreateInstance ) - 这是讨厌的一个。非常微妙。事实证明,加载程序可以使用COM( HKCR\CLSID )从注册表中查找DLL文件的完整路径。 LoadLibrary 将不会进行任何搜索,如果用户给它一个完整路径,因此激活上下文不能影响DLL文件解析。那些可以使用 comClass 元素和朋友重定向,请参阅[参考] [msdn_assembly_ref]。
- 即使你有正确的清单有时候,有人还可以使用。如果是这种情况,通常可以做的不多(参见下面的最终解决方案);这只是为了完整。如果你想知道是谁搞砸了激活的上下文,WinDbg bp kernel32!ActivateActCtx 。
- Explicit linking (LoadLibrary) -- the loader uses the current activation context of the running EXE file. This is intuitive.
- Implicit linking ("load time linkage", the "auto" ones) -- the loader uses the default activation context of the depending DLL file. If A.exe depends on B.dll depends on C.dll (all implicit linkage), the loader will use B.dll's activation context when loading C.dll. IIRC, it means if B's DllMain loads C.dll, it can be using B.dll's activation context -- most of the time it means the system-wide default activation context. So you get your Python DLL from %SystemRoot%.
- COM (CoCreateInstance) -- this is the nasty one. Extremely subtle. It turns out the loader can look up the full path of a DLL file from the registry using COM (under HKCR\CLSID). LoadLibrary will not do any searching if the user gives it a full path, so the activation context can't affect the DLL file resolution. Those can be redirected with the comClass element and friends, see [reference][msdn_assembly_ref].
- Even though you have the correct manifest, sometimes someone can still change the activation context at run time using the Activation Context API. If this is the case, there is usually not much you can do about it (see the ultimate solution below); this is just here for completeness. If you want to find out who is messing with the activation context, WinDbg bp kernel32!ActivateActCtx.
真实世界的解决方案
而不是使用这个WinSxS的东西,尝试使用 LoadLibraryW codefromthe70s/mhook22.aspxrel =nofollow noreferrer> Mhook 或 EasyHook 。您可以用您的自定义逻辑完全替换该调用。你可以在午餐前完成这个工作,再次找到生活的意义。
Real world solution
Instead of fiddling with this WinSxS thing, try hooking LoadLibraryW using Mhook or EasyHook. You can just totally replace that call with your custom logic. You can finish this before lunch and find the meaning of life again.
[msdn_assembly_ref]: 装配清单
[msdn_assembly_ref]: Assembly Manifests
更多推荐
DLL文件通过清单加载两次DLL重定向
发布评论