Can I use two incompatible versions of the same DLL in the same process?

前端 未结 7 1179
孤独总比滥情好
孤独总比滥情好 2020-12-31 11:45

I\'m using two commercial libraries that are produced by the same vendor, called VendorLibA and VendorLibB. The libraries are distributed as many DLLs that depend on the com

相关标签:
7条回答
  • 2020-12-31 11:48

    It is actually possible to implicitly load different versions of a dll into a single process.

    Doing this entails:

    1. Creating two assemblies, each containing a version of the dll that must be loaded multiple times. Sounds complicated but practically it entails little more than creating (2) named sub folders, each with a .manifest file containing some xml, and its own copy of the dll. So, VendorUtilsAssemblyV1 and VendorUtilsAssemblyV2

    2. Making each dependent dll use the assembly mechanism to resolve the implicit dependency - by adding a assemblyDependency directive that explicitly identifies VendorUtilsAssemblyV1 or V2.

    There are some options for point 2. If the VendorLibA and VendorLibB files do not contain their own manifests, then you can simply add manifest files with the required dependentAssembly directive named VendorLibA.2.dll.manifest and VendorLibB.2.dll.manifest. If they already contain manifests (probably to link to the VS2005 or VS2008 C-Runtime) then use the MT.EXE tool to merge in the new dependency.

    0 讨论(0)
  • 2020-12-31 11:55

    I'm no expert in DLLs, but the only way I see it possible would be to use LoadLibrary() and explicitly load the DLLs. Then you could place the functions/classes etc in separate namespaces using GetProcAddress().

    HMODULE v1 = LoadLibrary(_T("libv1_0.dll"));
    libv1_0::fun_in_lib = reinterpret_cast<FUNTYPE>(GetProcAddress(v1, _T("fun_in_lib"));
    

    and

    HMODULE v2 = LoadLibrary(_T("libv2_0.dll"));
    libv2_0::fun_in_lib = reinterpret_cast<FUNTYPE>(GetProcAddress(v2, _T("fun_in_lib"));
    

    Whether this would work or not still kind of depends on the library, so it may or may not work, but as far as I can tell it's the only possibility.

    0 讨论(0)
  • 2020-12-31 11:55

    You mean, you have a situation similar to MSVCRT80.DLL and MSVCRT90.DLL ? There is a good reason Microsoft numbered these DLLs.If both were called MSVCRT.DLL, only one of them would be loaded in a single process.

    0 讨论(0)
  • 2020-12-31 11:57

    I had a similar problem. Specifically I wanted to use a PyQt from a Python interpreter embedded in an application that was using an incompatible version of Qt. There were two Qt DLLs used by the primary application: QtCore.dll and QtGui.dll.

    When I would load PyQt from the embedded Python interpreter, I would get an error:

    ImportError: DLL load failed: The specified procedure could not be found.
    

    This occured on the line:

    from PyQt4 import QtGui
    

    The problem is that the once an incompatible QtGui.dll is loaded into the main application's process space any references to QtGui.dll (e.g. from the file QtGui.pyd) are incorrect.

    What happened next, I am not proud of.

    First I renamed QtGui4.dll in the PyQt distribution to QtGuiX.dll and then renamed the QtCore4.dll to QtCoreX.dll. Notice that the renaming maintained the same number of characters, this is important.

    Next I opened the file QtGui.pyd in Notepad++, and replaced all plain-text references of QtGui4.dll to QtGuiX.dll and from QtCore4.dll to QtCoreX.dll. I repeated the process for the files: QtCore.pyd, QtGuiX.dll and QtCoreX.dll.

    Finally I checked that my PyQt test application still worked. It did! Then I tried running the PyQt test application from the embedded Python interpreter, and it worked as well.

    So, it seems to works in a couple of trivial cases. I expect that I need to repeat the process for all DLLs and PYDs in the PyQt distribution.

    This is probably not the right way to do things, but I can't think of any concrete reasons how it could blow up (other than if I change the length of the file name).

    Credit (or blame) to others on the thread for inspiring this terrible tale.

    0 讨论(0)
  • 2020-12-31 12:03

    As you are not using VendorLibUtils directly, I assume you can't use LoadLibrary etc.

    If the VendorLibUtils DLLs only have exports by ordinal, you could probably rename one of the the libraries and patch the corresponding VendorLibX to use a different filename for its imports.

    If the VendorLibUtils DLLs have one or more exported symbols with the same names, you might need to patch the imports and export tables too, but let's hope not! :-)

    0 讨论(0)
  • 2020-12-31 12:11

    I think your most promising option is to complain, loudly, to the vendor who is distributing mutually incompatible products. That rather goes against the idea of a DLL.

    You can't just put the DLLs in different directories. Once a DLL with a given name is loaded, all other attempts to load another DLL with the same module name will simply use the one that's already loaded, even if the paths are different.

    From that, we can conclude that to load two copies of VendorLibUtils, one copy needs to have a different name. You can't just rename the DLL file; the code in your program won't know to look for the different file. Therefore, perhaps there's a way to edit the import table of VendorLibB to make it think the functions it needs are in VendorLibUtilsB.dll instead of just VendorLibUtils.dll. I'm afraid I don't know of any utility that will do that, but I have little doubt it's possible to do.

    0 讨论(0)
提交回复
热议问题