DLL文件通过清单加载两次DLL重定向 [英] DLL file loaded twice with DLL redirection through manifest

查看:300
本文介绍了DLL文件通过清单加载两次DLL重定向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 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.manifest

python25.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 http://dl.dropbox.com /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 B.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.

  1. 查找导致DLL文件加载的最简单的方法是使用过程监视器。您可以观看包含 python25.dll 路径,其中包含 python25。 dll (用于COM查找)。双击一个条目实际上会显示一个堆栈跟踪(您需要首先设置符号搜索路径,并设置Microsoft的PDB服务器)。这对您的大部分需求都是足够的。

  2. 有时,从上方获取的堆栈跟踪可能会从一个新的线程中产生。为此,您需要 WinDbg 。这可以是另一个主题,但足以说你可以 sxe ld python25 ,看看其他线程正在做什么(!findstack MyExeModuleName 〜* k ),导致加载一个DLL文件。

  1. The easiest way to find out what causes a DLL file to load is to use Process Monitor. You can watch for "Path containing python25.dll" or "Detail containing python25.dll" (for COM lookups). Double clicking an entry will actually show you a stack trace (you need to set the symbol search paths first, and also set Microsoft's PDB server). This should be enough for most of your needs.
  2. Sometimes the stack trace obtained from above could be spawned from a new thread. For this purpose you need WinDbg. That can be another topic, but suffice to say you can sxe ld python25 and look at what other threads are doing (!findstack MyExeModuleName or ~*k) that causes a DLL file to load.



< h3>真实世界的解决方案

而不是使用这个WinSxS的东西,尝试使用 LoadLibraryW http://codefromthe70s.org/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重定向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆