When vendors release different versions of COM components, they retain the binary compatibility to make sure that programs which are compiled with one version of the component work with another version (at least backward compatible). Examples are ADODB, MSXML etc. But sometimes, an odd chicken is hatched and this binary compatibility is broken. This situation creates problems in development, and different versions of project files have to be created. Any references in a Visual Studio project for the libraries built around that COM component have to be changed when working with different versions. This article discusses a strategy to facilitate development using different versions of the same COM component whose binary compatibility is broken.
Right click on References in project tree, and in Add Reference dialog, select COM tab. Select the COM component from the displayed list or Browse for the library file. Visual studio uses the tlbimp tool to generate an Interop wrapper over the component. This wrapper assembly is named Interop.library.dll by the project. This assembly is identified by the type library GUID and is shown as Identity in Assembly Properties as shown here:
When binary compatibility is broken with different versions of the COM component, the library GUID changes and the Interop assemblies are no longer compatible. But in our case, the library name in the type library has not changed. That means the namespace library does not change. To simulate this situation, I have created a simple COM component using Visual Basic 6.0. This code contains a library called TestDll with a component called TestComp. This component has one method DisplayTestMessage() which will display a message giving the version number.
TestComp
DisplayTestMessage()
Below are the Visual Basic project settings which broke the binary compatibility:
Using this code, I have created two versions of the COM component, 1.0.0.0 and 2.0.0.0, and placed them in different directories. The differences, in the components generated, will be the GUIDs (Identity) and the message box. The library name, component name, and method signature are all same. Now, to use this component in a .NET project, the following code is used:
using System;
using System.Windows.Forms;
using TestDll;
namespace TestReference
{
public class TestForm : System.Windows.Forms.Form
{
static void Main()
{
TestDll.TestCompClass test = new TestDll.TestCompClass();
test.DisplayTestMessage();
}
}
}
When we try to add reference to both the versions in a test application by selecting the DLLs in Add Reference dialog, after one DLL is added, for the second DLL, Visual studio gives the following error because the namespace is same:
To avoid this warning message, here is a solution:
<Reference
Name = "TestDll_1.0.0.0"
Guid = "{CB8AD23D-7243-4DF6-A7D2-77E8B9AC4993}"
VersionMajor = "1"
VersionMinor = "0"
Lcid = "0"
WrapperTool = "tlbimp"
/>
Important: Remember to save the project in Visual Studio to see the changes in .csproj or .vbproj file!
Now we have a project referencing both the versions, and interestingly, you can tell from the project visually which version of DLL your project is using and the program is compiled with, by looking at the small warning icon (see the image below). To simulate a real world situation (where only one version of component is installed), rename one of the COM component DLL files, and recompile the project. A warning icon appears in the Visual Studio but the program still works with whichever version is available.
The technique discussed above only makes development environment easier. But while deploying, we still have to make sure to build the correct version of the Interop assembly targeting the clients, and deploy it with the executable, mainly because the names of the assemblies will be same across different versions of COM.