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>
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
is now loaded twice: the one requested by the manifest, and the one that Windows should find through its search order.
Screendump of Process Explorer http://dl.dropbox.com/u/3545118/python25_dll.png
Why is that happening and how can I just load the DLL file pointed by the manifest?
After exhaustive battle with WinSxS and DLL redirection, here's my advice for you:
Various things can cause a DLL file to be loaded under Windows:
LoadLibrary
) -- the loader uses the current activation context of the running EXE file. This is intuitive.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%
.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].bp kernel32!ActivateActCtx
.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.sxe ld python25
and look at what other threads are doing (!findstack MyExeModuleName
or ~*k
) that causes a DLL file to load.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]: Assembly Manifests
I made some progress for the understanding of the issue.
First let me clarify the scenario:
python25.dll
in the same folder as my DLL file, as well as a boost_python-vc90-mt-1_39.dll
.Then, when running the EXE file, the current directory is not the one containing python25.dll
, and that's why the search order is used and some other python25.dll
can be found before mine.
Now I figured out that the manifest technique was the good approach: I managed to redirect the loading to "my" python25.dll
.
The problem is that this is the Boost DLL file boost_python-vc90-mt-1_39.dll
that's responsible for the "double" loading!
If I don't load this one, then python25.dll
is correctly redirected. Now I somehow have to figure out how to tell the Boost DLL file not to load another python25.dll
...
Dependency Walker is usually the best tool for resolving this kind of problem. I'm not too sure how well it handles manifests though...
Where in this entangled mess is the actual process executable file?
Two possibilities come to mind:
You are writing a Python extension DLL file. So the Python process is loading your DLL file, and it would already have its own python25.dll dependency.
The EXE file loading your DLL file is being built with header files and libraries provided by the DLL file project. So it is inheriting the #pragma comment(lib,"python25.lib")
from your header file and as a result is loading the DLL file itself.
My problem with the second scenario is, I'd expect the EXE file, and your DLL file, to be in the same folder in the case that the EXE file is implicitly loading your DLL file. In which case the EXE file, your DLL file and the python25.dll are all already in the same folder. Why then would the system32 version ever be loaded? The search order for implicitly loaded DLL files is always in the application EXE file's folder.
So the actual interesting question implicit in your query is: How is the system32 python26.dll being loaded at all?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With