Invoking GetMethod() on a System.__ComObject always returns null

1

I am using .NET 4.0 and dynamic to invoke members on a System.__ComObject at runtime. I instanciate the object in the following way:

dynamic DrApi;
DrApi = Activator.CreateInstance(SprImportedTypes.DrApi);

The types are declared in a static class like this:

internal static Type DrApi = Type.GetTypeFromProgID("DrApi.DrApi.1");

Since the object is dynamic, I can invoke methods without any difficulty:

string vers = string.Empty;
DrApi.Version(ref vers);

For consolidation and localized error handling, I'm trying to have a single routine that can be used for invoking methods on that object. Most of the methods require ref/out parameters, so I'm currently returning an object array of values that gets returned from reflection:

public object[] Run(string method, params object[] args)
{
    var p = new ParameterModifier(args.Length);
    for (int i = 0; i < args.Length; i++)
        p[i] = true;
    ParameterModifier[] mods = { p };

    SprImportedTypes.DrApi.InvokeMember(method, BindingFlags.InvokeMethod,
                                        null, DrApi, args, mods, null, null));

    return args;
}

While this works, I'm not getting any information on the method I'm invoking, and am therefore not 100% comfortable setting all of the parameters by reference.

Here's what I tried that isn't working:

MethodInfo mInfo = SprImportedTypes.DrApi.GetMethod(methodName, BindingFlags.Instance |
                                                    BindingFlags.NonPublic | BindingFlags.Static);

Here is the method from OLE TypeLib Viewer:

[id(0x00000009), helpstring("method Version")]
HRESULT Version(
            [in, out] BSTR* VersionString, 
            [out, retval] long* pReturnValue);

The class implements an interface which itself implements IDispatch, and the method is HRESULT, so I can't figure out why it never returns anything.

c#
reflection
com
late-binding
asked on Stack Overflow Feb 11, 2014 by Parrish Husband • edited Feb 11, 2014 by Parrish Husband

1 Answer

2

This cannot work, COM does not support Reflection. So you cannot expect Type.GetMethod() to return anything. Late binding in COM is one-way, you can ask the server to execute a method by name but it won't tell you what methods it supports and what arguments they take. You are supposed to know this from the documentation.

You actually have a type library so technically you can inspect it at runtime to see what it is inside. This is far beyond painful and utterly impractical. Far simpler is to just add a reference to the type library. And you'll get auto-generated .NET wrapper types that you can use directly in your code. Check the MSDN article about Tlbimp.exe for details. This turns on lots of goodies, like IntelliSense and compile-time error checking. The code runs a lot faster as well. No need for dynamic anymore. The only disadvantage is that you'll bind your code to a specific version of the COM server, the one you have the type library for. But you'll of course still crash when your late-bound call is not compatible with an update, there is no magic cure for that.

answered on Stack Overflow Feb 11, 2014 by Hans Passant

User contributions licensed under CC BY-SA 3.0