1
votes

I’m working with a .NET 4 application written mostly in C#. The application has a user interface, but it also has an automation interface that allows the features of the application to be exploited directly from a .NET client. It also supports automation via COM, and for this there are “COM adapter” DLLs that present the classes/methods in the “real” DLLs in a COM-friendly way.

For example, let’s say the API for the bulk of the functionality is in a DLL called “Alpha.DLL”: a .NET client can simply reference that DLL directly, but a separate DLL called “Alpha.Com.DLL” is provided for use by COM clients (e.g. VBA).

There are 3 such COM adapter DLLs, and while two work fine, I simply cannot get the last one to work correctly.

The problem DLL only has two classes defined within it, and while I can instantiate one of them from a COM client such as VBScript, I get an error when I try to instantiate the other. The error I get is:

-2146234304 (0x80131040) Automation Error

I can instantiate the same class from .NET code, just not from a COM client.

I’ve tried using FUSLOGVW.EXE to look for assembly-loading errors, but there don’t seem to be any (and in any case, the fact that I can instantiate the other class from the same DLL suggests that it’s not the DLL itself that can’t be found/loaded?).

I’ve tried attaching a debugger and putting a breakpoint inside the constructor for the offending class, but it doesn’t get hit when I try to instantiate the class from VBScript. (A breakpoint in the constructor of the class that works does get hit).

I’ve checked the registry entries for the class I’m trying to instantiate, and I can’t see any problem. The GUIDs and version numbers all seem to match up.

I’m all out of ideas, and at the end of my tether, and I’d be extremely grateful for some help…

3
There's not much to go on here. You haven't even shown us what the external API of the DLL looks like.Robert Harvey
@RobertHarvey I wasn't sure whether it would be relevant - I had hoped that someone might point me at a diagnostic tool for me to keep doing the spade-work myself. To describe the scenario in full will likely take me a couple of hours, and I can't do it from here (home), but I'll try tomorrow.Gary McGill

3 Answers

3
votes
  -2146234304 (0x80131040) Automation Error

The common problem with using .NET code from a COM client like VBA is that .NET exceptions get rather difficult to diagnose. You have to make do with an often cryptic HRESULT error code, you don't get the Holy Stack trace to see how code blew up. This exception is a doozy like that, it is FUSION_E_REF_DEF_MISMATCH, you can find these HRESULT codes in the CorError.h SDK include file.

You'd normally get the easier to interpret exception message "The located assembly's manifest definition does not match the assembly reference". And the stack trace to tell you what type caused this exception so you'll know what assembly is the problem. Nothing like that when this failed when called from VBA.

It is otherwise an every-day .NET mishap, the CLR found your assembly but its [AssemblyVersion] does not match the reference assembly's version that your code was compiled with. COM certainly increases the odds that this can go wrong, the version is recorded in the registry when you register the assembly with Regasm.exe. Forgetting to re-register if you do it by hand instead of letting the build system take care of it is a very easy oversight. Also very easy to copy dependent DLLs in the client EXE's directory, so the CLR can find them, and forgetting to update them.

Fuslogvw.exe does show this kind of mishap, hard to guess why you don't see anything. The backup plan is to use SysInternals' Process Monitor. It also shows you how the client is reading the registry, another thing that often goes wrong in COM. And you'll see it locating the DLL from the registry key so you'll have a shot at guessing why it found an old one.

Stay out of trouble by using the GAC, often necessary anyway to help the CLR to find dependent assemblies and to solve COM's rather severe DLL Hell problem. And strongly consider using the .NET 4 AppDomain.FirstChanceException event. Good to log exceptions before they turn undiagnosable in the COM client.

1
votes

please check first

  1. your com dll is placed into GAC
  2. you dont't forget about regasm http://www.jagjot.com/2014/01/register-c-vb-net-dll-regasm-gacutil/
  3. check cpu architecture
  4. does your com dll depends on anything outside GAC?
0
votes

Aaargh. I found the problem. I said in my question:

I’ve checked the registry entries for the class I’m trying to instantiate, and I can’t see any problem. The GUIDs and version numbers all seem to match up.

...which was true. However, what I had not noticed was that in the registry definition of one of my classes, the public key token was wrong.

This explains why one class could be instantiated while the other could not, and possibly why there was nothing in the FUSLOGVW log (because the assembly was loaded OK when an instance of the "good" class was created).

Thanks for your help, Hans and Dimzon.