简体   繁体   中英

How can a C# program use a COM dll of any version?

This question is a sequel of this question

We're creating a dll, written in C++, providing access to some hardware. This dll implements and is accessed using COM interfaces. We also have a C# program that uses this dll through the COM objects.

We're having an issue with the versions. Indeed, when running the C# program, it absolutely wants to use the exact COM/C++ dll version it used when compiling. Ie if the C# program was compiled using COM/C++ dll 1.2.3.4, then the program will refuse to run with COM/C++ dll 1.2.3.5.

Unhandled Exception: System.TypeInitializationException: The type initializer for 'MyDllVerify.App' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'MyCorp.MyDll.Interop, Version=1.2.3.4, Culture
=neutral, PublicKeyToken=ced78d295d1e0f2b' or one of its dependencies. The system cannot find the file specified.
File name: 'MyCorp.MyDll.Interop, Version=1.2.3.4, Culture=neutral, PublicKey Token=ced78d295d1e0f2b'   at MyDllVerify.App..cctor()

I'd like to instruct the C# program to use any COM/C++ dll with version 1.2.anything.

Where can I configure this in the C# project?

I would suggest you to not directly reference to the COM-dll in your C# project. If you do that, at build time there is always a new COM-interop-dll generated. This can lead to a lot of problems.

It would be a better approach to create a COM-interop-dll, store it in your library folder and reference this library in your C# project. Keep this COM-interop-dll as static as possible. If you do it like that, you can replace the used COM-dll as much as you want, as long as your interfaces do not change.

You could try to manipulate this interop assembly and make the version checking for 1.2.* there, if you realy want that (I would not recommend to that, it could cause serious confusion).

Explanation: The COM-interop-dll is a regular .NET assembly. It works like a wrapper between your C# code and the COM-C++-code you want to use in the C# code.

The COM-interop-dll don't have to be registered for COM. You can install this assembly so many times you like. But it requires that your COM-dll is registered for COM.

Useful tools:

  • tlbimp
  • regasm
  • sn

Nothing is different from the way I documented it in your previous question. You still use <bindingRedirect> to allow the wrong version of the interop assembly to be loaded.

It is fairly unlikely to work in practice, messing with DLL Hell when you use COM is extremely unwise. If you use early binding then COM has no way to verify that you are calling the correct method. Very unlike .NET where the jitter can make checks like these at runtime from the metadata in the assembly. If the C++ programmer did it right then he changed the guids of the types that he changed. Which will make your code bomb with E_NOINTERFACE since you'll use the guid of the old version.

If he didn't, unfortunately way too common, then your program is liable to crash with something nasty like an AccessViolationException. Or worse, it won't crash but will call the completely wrong method.

The failure mode is more benign when you use late binding, you'll get one of the IDispatch errors when the method doesn't exist or if its arguments have changed. Not that this ultimately solves anything, you still have a program that doesn't work. Mess with DLL Hell like this only if you like to live dangerously.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM