4

I'm working on some legacy code that creates a list of strings containing property and/or method names and then attempts to apply those properties or methods to a COM object. The property or method for the COM object is not guaranteed to exist and it could be either a property or a method I don't know which.

At the moment if a property or method doesn't exist it's caught as a COM exception. This results in poor performance. I am trying to find a way to check if a property or method exists in a COM object without generating an exception so that I can check for its existence before attempting to apply it.

Using GetType returns type System.com_object. Using GetProperty on System.com_object doesn't work as this is the exact runtime type not the type it's derived from. Instead I have to InvokeMember which creates an exception if the member doesn't exist. Does anyone have a better way of doing this?

I'm working in .NET 3.5 at the moment. Migration to .NET 4 is not an option at present but I'd still be interested in solutions in .NET 4 if the new language features provide a better way of solving the problem.

public static bool CheckIfComPropertyOrMethodExists<T1>(T1 objectToCheck, string propertyOrMethodName)
{
    if (CheckIfComPropertyExists(objectToCheck, propertyOrMethodName) == false & CheckIfComMethodExists(objectToCheck, propertyOrMethodName) == false) {
        return false;
    }
    {
        return true;
    }
}

public static bool CheckIfComPropertyExists<T1>(T1 objectToCheck, string propertyName)
{
    return objectToCheck.GetType().InvokeMember(propertyName, BindingFlags.GetProperty, null, objectToCheck, null) != null;
}

public static bool CheckIfComMethodExists<T1>(T1 objectToCheck, string methodName)
{
    return objectToCheck.GetType().GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance) != null;
}

Helpful articles so far

How to check whether an object has certain method/property?

Calling a member of IDispatch COM interface from C#

http://msdn.microsoft.com/en-us/library/aa909091.aspx

Implementing IDispatch in c#

http://msdn.microsoft.com/en-us/magazine/dd347981.aspx

http://blogs.msdn.com/b/lucian/archive/2008/10/06/reflection-on-com-objects.aspx

Community
  • 1
  • 1
dior001
  • 751
  • 1
  • 13
  • 32

1 Answers1

1

Most probably the COM class implements also the IDispatch interface. You could then use its GetIDsOfNames to check whether a member exists in the class.

Here someone calls it from C#:

Calling a member of IDispatch COM interface from C#

Community
  • 1
  • 1
Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
  • Thank you for your answer. I think GetIDsOfNames will solve the problem. I will accept your answer shortly. I was wondering if you would mind expanding your answer with an example as I'm having difficulty understanding http://stackoverflow.com/questions/8068449/calling-a-member-of-idispatch-com-interface-from-c-sharp. I am trying to access members of Microsoft.Office.Interop.Excel . How do I GetIDsOfNames for a class if I don't know the underlying type of the class I'm applying GetIDsOfNames to? All I have is a System.com_object. That could be any type in Microsoft.Office.Interop.Excel namspce – dior001 Jul 18 '12 at 12:58
  • 1
    You just cast your COM object to IDispatch, it does not matter what type the object is, it implements IDispatch for sure. – Wiktor Zychla Jul 18 '12 at 16:26
  • GetIDsofNames throws a DISP_E_UNKNOWNNAME COM exception if the member doesn't exist. This means I still have the same performance problem. Any ideas how to do this without an exception? I tried the following http://stackoverflow.com/questions/11665813/object-of-type-system-int32-cannot-be-converted-to-type-system-uint32 without any success. – dior001 Jul 30 '12 at 13:16
  • 2
    (Six years later...) You can mark the GetIdsOfNames with a [PreserveSig] attribute, letting it return the HRESULT directly without an exception raised for the error case. – Govert Apr 20 '18 at 22:16