Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Techniques for resolving COM-related error 0x80040154?

Updated with more debugging info

I'm running a proprietary software package that I don't have source for, and it has a plugin interface that is COM-based. I have a .NET assembly that is COM-visible that the application successfully loads on one computer, but not on another.

I've been working for the past two days on this problem, and I feel like I am aimlessly wandering the COM landscape. On the system that doesn't load my plugin, when I use regasm /codebase /tlb, the tlb is generated and registered successfully.

When I look at the only log file available to me, it mentions that it can't create the object, and returns the error code 0x80040154.

I can't figure out why the object can't be created, and am hoping that someone can suggest some debugging strategies. Here is what I have already tried, without success:

  • copy my DLL and its dependencies from the working computer to the non-working computer
  • installing VS2010 on the non-working computer (the working computer had it installed)
  • comparing the results of Dependency Walker for my DLL and its dependencies on both computers (they were identical)
  • used ListDLLs. Both systems load the same DLLs
  • ran Process Monitor and filtered on the CLSID for the assembly while running regasm /codebase /tlb. Both logs were identical except for the PIDs and datestamps, even though the working system create the tlb and registered successfully, and the non-working system registered the assembly, but didn't create the tlb.
  • ran Process Monitor and filtered on the CLSID for the assembly while running the application. The working system had several entries in the log, but the non-working system had none, which I believe is expected since the tlb didn't get created.
  • looked at OleView on working system, which had the assembly listed with the typelibrary beneath it. The non-working system had the assembly listed, but did not have an associate type library. See below.

Here are the the differences between the assembly's entry in OleView on the working and non-working systems:

  • Working system has an entry under the assembly that I assume corresponds to the typelibrary that was generated and registered. Non-working system does not.
  • _Object on non-working system has an extra value under CLSID called InprocServer32[InprocServer32] = (gibberish here).
  • IConnectionPointContainer on non-working system has the same InprocServer32 entry as above
  • same for IDispatch, IManagedObject, and IProvideClassInfo

I'll look through the registry, and perhaps I need to remove those extra entries and try to run regasm again?

EDIT -- I solved the problem. Thanks everyone for your help. It turns out that a file was missing on both systems, but for whatever reason, regasm worked on one, and not the other. I'm suspicious that there may have been a change where a dependency was copied to a folder that was in the system path! So I did a hail mary, copied over the dll, and regasm executed without any messages. And then the application loaded the plugin successfully!

like image 460
Dave Avatar asked Jul 15 '11 18:07

Dave


2 Answers

I'm assuming that the component generating the "class not registered" error is yours, right? In other words, are you sure from the log that it's trying to CoCreate your object? Just a sanity check.

You might want to try directly creating your COM object using a tool like Oleview.exe. It's been a while since I've used it but I remember that you can find your class, then try to instantiate it directly.

You also might want to fire up a tool like procmon (sysinternals.com) and capture what registry entries are being read at the time that the error occurs. Filter on RegOpenKey operations (Operation is RegOpenKey) and look for unsuccessful results (Result is not SUCCESS). It's a bit tedious but by comparing the reg traces between the 2 machines it might point you to the answer.

Good luck!

John

like image 175
JohnD Avatar answered Sep 29 '22 00:09

JohnD


That it works on your dev machine and not the target machine and that they are identical eliminates many possible failure modes. There's only one left: it works on your dev machine because you let the IDE register the assembly for you. In which case you use Regasm.exe incorrectly. You must use it with the /codebase option. Forget about the /tlb option, that's for compilers.

With /codebase, the assembly gets registered in the directory it is located. You'll get a warning from Regasm, telling you that you are about to enter DLL Hell. Nothing you can do about that in this case so ignore that warning. Without /codebase you must put the assembly in the GAC with gacutil.exe so the assembly can be found.

The ultimate troubleshooting strategy is to use SysInternals' ProcMon utility and look at the trace records that show the app searching for the COM component. You'll see it poking the HKLM\Software\Classes\CLSID\{guid} key for the registration info. Compare with what you see using Regedit.exe. If you see Wow6432Node getting searched then you're running on a 64-bit operating system and have to use the 32-bit version of Regasm.exe to register the assembly.

like image 30
Hans Passant Avatar answered Sep 29 '22 01:09

Hans Passant