views:

533

answers:

3

I am using COM Object in my C# .NET 1.1 application. When the COM object is not registered on client machine, I get the exception:

"COM object with CLSID {} is either not valid or not registered." (HRESULT:0x80040154)

I know how to register the COM object using regsvr32. Our requirement is to identify the COM object which is not registered. We don't want to hardcode the name of the COM Object, rather identify it dynamically using the COM Exception/HResult. Any ideas?

+1  A: 

The only way to solve the problem you describe is to have a global list of CLSIDs for all objects you want to check.

If you only care about a few libraries, you can install them, check their GUIDs, and build this database yourself.

If you want to identify any possible library worldwide that might ever exist, I would give up now and have some coffee.

Bork Blatt
A: 

If I understand you correctly you get the message "I don't know how to find the COM object for this GUID" and want to do it better..? In other words: Usually you'd register the COM object and it is referenced by its class id or ProgId. For now windows doesn't know about your target object.

I'm not sure how to do that. If your COM objects are .Net assemblies you might be able to use Reflection to iterate over a list of files in your program directory and lookup the relevant attribute, comparing it with the error message. If they are native libraries there are probably P/Invoke ways to do the same, but I wouldn't know how and Google doesn't help so far.

I would love to understand the requirement though: Since you're distributing that app and know the dependencies, why do you want to add this extra layer of complexity?

Benjamin Podszun
We have a bunch of COM objects, which are registered by the application installer. However, certain users complain that they get "Specified module not found" (means the .ocx file has been moved from the path mentioned in registry) or "COM Object with CLSID {...} not registered" (.ocx not registered) exceptions.We want to handle this exception in the code to tell the end-user which .ocx file has been moved, or is unregistered. We don't want to hard-code the exception messages for each .ocx.
NEDian
+1  A: 

Given the situation mentioned in the comment to Benjamin Podszun's answer, your approach could be:

  • Look up the CLSID in the registry (HKEY_CLASSES_ROOT\CLSID\{...})
  • If not found, just throw so that the generic error message is displayed
  • Look at the appropriate subkey depending on the type of object (e.g. InProcServer32 for an in-proc native COM DLL/OCX). The default value will be the path to the DLL/OCX.
  • Check for the existence of this path and fabricate a suitable message with the name of the file.

This enables you to display a different message if the OCX/DLL has been moved, but of course won't help if it is not registered.

You also might want to spend some time trying to understand why (or even five whys!) the components are being moved / unregistered on some client machines, which may suggest a way to prevent it . For example, one possible scenario is that the user installs version 1, then installs version 2, then uninstalls version 1. Depending on how your installer is implemented, uninstalling version 1 may deregister or remove the components needed for version 2.

Another approach might be to see how the installer behaves as a normal user vs an administrator.

Identifying the exact sequence of events on failing client machines may be a bit of a challenge, but it's worth trying.

Joe