How to load 2 dlls with same name but different versions

From the title it might seem that the easiest way to do this is by using Loadlibrary. However on many occasions you might end up in a scenario where one or more third party dlls might be in question. For ex, a third party dll is loading A.dll and you also want to load A.dll of a different version. In general , I will be summarizing you how to load 2 different versions of the same dll without using Loadlibrary.

The scenario here is , I have hello.exe which loads intermediate.dll (third party) , intermediatemine.dll(mine) and in turn intermediate.dll will load A.dll (v1.0) and intermediatemine will load A.dll(v2.0) . I have the code for intermediatemine.dll , I do not have control for intermediate.dll .Now if we code like below in hello.exe and try to isolate the dlls to be 2 folders , it would not be enough .

In the Visual Studio sln , I have hello.exe and intermediatemine.dll and A.dll(v2.0)

The folder structure is

..\hello\hello\Debug\1 -->contains A.dll (v1.0) & intermediate.dll

..\hello\hello\Debug\2 -->contains A.dll(v2.0)  & intermediatemine.dll

..\hello\hello\Debug--> contains the exe

The below is the an attempt to load the dlls separately which is not sufficient.

cout << "Entering Main" << endl;

em = SetErrorMode(SEM_FAILCRITICALERRORS);

SetDllDirectory(L"1");

HINSTANCE hDll_1 = ::LoadLibrary(L"1\\intermediate.dll");

SetErrorMode(em);

 

if(!hDll_1)

 {

cout << "Error loading intermediate.dll. Code: "
<< ::GetLastError() << endl;

return 1;

  }

 

 funcptr p_func1 =  reinterpret_cast<funcptr>(::GetProcAddress(hDll_1,
"SomethingA"));

if(!p_func1)

{

      return 1;

 }

 

p_func1();    // This call is in A.dll(v1.0)

 

funcptr p_func2 =  reinterpret_cast<funcptr>(::GetProcAddress(hDll_1,"SomethingB"));

if(!p_func2)

{

return 1;

}

 

 p_func2();    // This call is in A.dll(v1.0)

 

em = SetErrorMode(SEM_FAILCRITICALERRORS);

SetDllDirectory(L"2");

HINSTANCE hDll_2 = ::LoadLibrary(L"2\\intermediatemine.dll");

SetErrorMode(em);

if (!hDll_2)

{

      cout << "Error loading intermediatemine.dll. Code: " << ::GetLastError() << endl;

      return 1;

}

 

funcptr p_func3 =  reinterpret_cast<funcptr>(::GetProcAddress(hDll_2, "SomethingC"));

   if (!p_func3)

{

      return 1;

}

 

p_func3();   // This call is in A.dll(v2.0)

funcptr p_func4 =  reinterpret_cast<funcptr>(::GetProcAddress(hDll_2, "SomethingD"));

if (!p_func4)

{

      return 1;

 }

 

 p_func4();  // This call is in A.dll(v2.0)

 

 pause();

 

 ::FreeLibrary(hDll_1);

 ::FreeLibrary(hDll_2);

This method uses manifest file to load the dlls.

Step 1 :Firstly create a manifest file like below  and save it in the folder where you have the intermediatemine project’s .cpp files,etc .

<?xml version="1.0" encoding="UTF-8"
standalone="yes"?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">

    <file name="A.dll" />

</assembly>

Save it in ..\hello\hello\intermediatemine

Step2 : Now open your Visual Studio and go to Project Properties and change the particular project Property as below .

Project Properties-->Manifest Tool-->Input and Output-->Additional Manifest Dependencies

and then add the manifest file as one of the additional dependency

..\hello\hello\intermediatemine\intermediatemine.private.manifest

We do this so, it normally creates A.dll.intermediate.manifest. it then merges that private manifest to make A.dll.embed.manifest ,it then runs the mt.exe as part of the build process to put the embed manifest into the DLL as resource #2.

Note that I have made the A’s Output folder as ..\hello\hello\Debug\2 .

So now when you rebuild your application and run. You will observe that the intermediate.dll from folder 1 loads the A.dll from folder 1 and  intermediatemine.dll loads the A.dll from folder 2.

I have added the output folder for intermediatemine.dll and A.dll in Visual Studio to Folder 2.

Now when I rebuild the application and run I see that the intermediate.dll from folder 1 is loading A from folder 1.

intermediatemine.private.manifest