C++ DLL文件加载两次,并通过清单进行DLL重定向
我将C++ DLL文件加载两次,并通过清单进行DLL重定向,c++,python,visual-studio,dll,manifest,C++,Python,Visual Studio,Dll,Manifest,我将python.h包含在我的DLL文件项目中,这会导致与python25.DLL的隐式链接。但是,我想加载一个特定的python25.dll(计算机上可能有几个),因此我创建了一个非常简单的清单文件test.manifest: python25.dll现在被加载两次:清单请求的一次,以及Windows应该通过其搜索顺序找到的一次 为什么会发生这种情况?我如何加载清单所指向的DLL文件?通常是解决此类问题的最佳工具。不过我不太确定它处理清单的效果如何 在这种混乱中,实际的进程可执行文件在哪里
python.h
包含在我的DLL文件项目中,这会导致与python25.DLL
的隐式链接。但是,我想加载一个特定的python25.dll
(计算机上可能有几个),因此我创建了一个非常简单的清单文件test.manifest:
python25.dll
现在被加载两次:清单请求的一次,以及Windows应该通过其搜索顺序找到的一次
为什么会发生这种情况?我如何加载清单所指向的DLL文件?通常是解决此类问题的最佳工具。不过我不太确定它处理清单的效果如何
在这种混乱中,实际的进程可执行文件在哪里
我想到了两种可能性:
#pragma注释(lib,“python25.lib”)
,因此加载DLL文件本身因此,查询中隐含的真正有趣的问题是:system32 python26.dll是如何加载的 我在理解这个问题上取得了一些进展 首先让我澄清一下情况:
- 我正在使用Python C API和Boost.Python构建一个嵌入和扩展Python的DLL文件
- 因此,我在dll文件所在的文件夹中提供了一个
,以及一个python25.dll
boost\u python-vc90-mt-1\u 39.dll
- 然后我有一个EXE文件,它是一个演示如何链接到我的DLL文件的示例:只要DLL文件可以在路径中找到,这个EXE文件就不必和我的DLL文件在同一个文件夹中(我假设最终用户可以也可以不把它放在同一个文件夹中)
python25.dll
的目录,这就是为什么使用搜索顺序,并且可以在我之前找到其他一些python25.dll
现在我发现清单技术是一种很好的方法:我设法将加载重定向到“my”python25.dll
问题在于,这是负责“双重”加载的DLL文件boost_python-vc90-mt-1_39.DLL
强>
如果我不加载这个,那么
python25.dll
将被正确重定向。现在,我必须想办法告诉Boost DLL文件不要加载另一个python25.DLL
..在与DLL重定向进行了彻底的斗争之后,我给你的建议如下:
一些背景
各种因素可能导致在Windows下加载DLL文件:
- 显式链接(
)--加载程序使用正在运行的EXE文件的当前激活上下文。这是直观的LoadLibrary
- 隐式链接(“加载时间链接”,即“自动”链接)--加载程序使用取决于DLL文件的默认激活上下文。如果
依赖于A.exe
依赖于B.dll
(所有隐式链接),加载程序将在加载C.dll
时使用C.dll
的激活上下文。IIRC,这意味着如果B的B.dll
加载DllMain
,它可以使用C.dll
的激活上下文——大多数情况下,它意味着系统范围的默认激活上下文。因此,您可以从B.dll
获取Python DLL%SystemRoot%
- COM(
)--这是一个令人讨厌的例子。非常微妙。事实证明,加载程序可以使用COM(在CoCreateInstance
下)从注册表中查找DLL文件的完整路径<如果用户提供完整路径,则code>LoadLibrary不会执行任何搜索,因此激活上下文不会影响DLL文件的分辨率。可以使用HKCR\CLSID
元素和好友重定向这些内容,请参阅[参考][msdn\u assembly\u ref]comClass
- 即使您拥有正确的清单,有时仍有人可以在运行时使用更改激活上下文。如果是这种情况,通常你对此无能为力(见下面的最终解决方案);这只是为了完整性。如果你想知道是谁在干扰激活上下文,WinDbg
BPKernel32!激活eACTCTX
python25.dll
”或“详细信息包含python25.dll
”(用于COM查找)。双击条目实际上会显示堆栈跟踪(您需要先设置符号搜索路径,还需要设置Microsoft的PDB服务器)。这应该足以满足您的大部分需求sxe ld python25
并查看其他线程正在执行哪些导致加载DLL文件的操作(!findstack MyExeModuleName
或~*k
)LoadLibraryW
。您可以用自定义逻辑完全替换该调用。你可以完成这个
<?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>
Configuration Properties -> Manifest Tool -> Input and Output -> Additional Manifest Files
-->$(ProjectDir)\src\test.manifest