Search code examples
windowsdlltransitive-dependencyactivation-context-api

How to specify which instance of an already loaded side-by-side assembly to use


I am creating a dll (A.dll), which is isolated (ISOLATION_AWARE_ENABLED), depends on dependency.dll and has a manifest file:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
    <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
    <assemblyIdentity name="my.assembly.name" version="1.0.0.0" type="win32"/>
        <file name="A.dll"></file>
        <file name="dependency.dll"></file>
    </assembly>

A.dll is loaded by an application app.exe, which itself depends on a different version of dependency.dll. The manifest ensures that both versions of dependency.dll are used side-by-side. No problem so far.

Now, A.dll loads another dll B.dll via LoadLibrary. B.dll is loaded from a foreign directory, depends on dependency.dll and actually needs to use the version of dependency.dll used by A.dll, which is already in memory.

The problem is that B.dll uses the version of dependency.dll used by app.exe, as this was the first version of a module with that name which has been loaded into memory.

Is there a way I can force B.dll to use the version of dependency.dll which has been loaded by A.dll?

Language is C++, if that's relevant.


Solution

  • I don't know if you can do this, but this would work in some of the cases where this comes up:

    <?xml version='1.0' encoding='UTF-8' standalone='yes'?>
        <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
        <assemblyIdentity name="my.assembly.name" version="1.0.0.0" type="win32"/>
            <file name="A.dll"></file>
            <file name="B.dll"></file>
            <file name="dependency.dll"></file>
        </assembly>
    

    If B.dll can't be made a static load because it is truly dynamically detected this won't work at all.

    If the "same" requirement is really only "same version", you could make another assembly:

    <?xml version='1.0' encoding='UTF-8' standalone='yes'?>
        <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
        <assemblyIdentity name="b.assembly.name" version="1.0.0.0" type="win32"/>
            <file name="B.dll"></file>
            <file name="dependency.dll"></file>
        </assembly>
    

    If neither of these cases hold, you two choices remaining:

    1) Do the out-of-process call.

    2) Implement your own DLL loader and make the dependency resolution work the way you want. This won't help if B.DLL does LoadLibrary("dependency.dll") itself.