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

时光毁灭记忆、已成空白 提交于 2020-05-13 17:43:11

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/21709626/invoking-getmethod-on-a-system-comobject-always-returns-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!