2

I have a 3rd party dynamically-linked-library given to me by a vendor. The library is object oriented. I'm currently trying to access this library from either .Net or C#, however, when trying to call methods, no methods are available in .Net Support for these libraries is given by a programmer working with Python. Here is the Python Sample I was given:

import win32com.client
OLSV = Win32com.client.Dispatch("LsvEmu.LsvEmulator")
OLSV.BaseUnit

Here is what I've tried in C#

using System;
using LsvComLib;
using System.Reflection;
using System.Reflection.Emit;
using LsvEmuLib;


namespace LsvDemo
{
    class Program
    {
        static void TestEmu()
        {
           //LsvEmu should include Connect, and ConnectEx methods
            var lsvEmu = new LsvEmulator();
           //EmulationMode is a property, and all that is available other 
            than ToString, etc
            Console.WriteLine(lsvEmu.EmulationMode);

            //Attempt to use reflection to find a Dispatch equivalent in C#
            Type mytype = (typeof(LsvEmulator));
            //public
            //No further methods found
            MethodInfo[] myArrayMethodInfo = mytype.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            DisplayMethodInfo(myArrayMethodInfo);

            //private
            //No further methods found
            MethodInfo[] myArrayMethodInfo1 = mytype.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            // Display information for all methods.
            DisplayMethodInfo(myArrayMethodInfo1);  
        }
}

What would be an appropriate equivalent to the Python Dispatch call? Furthermore, why are the expected methods not available through reflection? It seems that this software vendor might not have access to all of the original source code, so I'm not sure how much help they would be. This library is meant to emulate another library they gave to us that makes ethernet calls to their devices. If lack of available methods shown via reflection is due to poor implementation, we may build our own emulator instead.

5unnyr4y3
  • 85
  • 1
  • 2
  • 11
  • Don't know much of `C#`, but Python's `Dispatch` is just an implementation of win [`IDispatch`](https://msdn.microsoft.com/en-gb/library/windows/desktop/ms221608(v=vs.85).aspx) interface. It's also well known in `VB` world due to `CreateObject` function. For your `C#` implementation try something like `dynamic OLSV = Activator.CreateInstance(Type.GetTypeFromProgID("LsvEmu.LsvEmulator");` or `object OLSV = Interaction.CreateObject("LsvEmu.LsvEmulator");` – CommonSense Nov 13 '17 at 15:34
  • Thanks! Do you happen to have any suggestions for use of such a call outside of the Visual Studio development environment? For example, if I'm using the .Net framework in a different environment, (such as Labview), Creating the instance of the dll fails because it is not registered, and unmanaged, and cannot be called by name as in CreateInstance. Is there a way to reference the dll location on disk when using GetType? – 5unnyr4y3 Nov 13 '17 at 20:31
  • As you said, this dll is unregistered in the system. As far as I know - you should register it if you want to use this interface, because such a `magic-word` in `Dispatch()` is a `ProgID` (which can be found in registry `HKEY_CLASSES_ROOT\CLSID\\ProgID` when things are registered). – CommonSense Nov 13 '17 at 21:17
  • Anyone has solution to this question as I am implementing something similar – Prany Mar 06 '19 at 11:49

1 Answers1

0

I recently implemented a .net solution for a similar situation using the built-in COM support in .net core 2 and up. This solution is registration-free. You still have the problem of figuring out what the data type you get is, but the object and dynamic types can help you with that.

So, the equivalent to the Python Dispatch would be two lines.

Type type = Type.GetTypeFromProgID("LsvEmu.LsvEmulator");
object inst = Activator.CreateInstance(type);

Now you have the program and interface to apply methods on. To get a property from it you would call InvokeMember() with Bindingflag.GetProperty

object result = (object)type.InvokeMember("BaseUnit", BindingFlags.GetProperty, null, inst, null);

Console.WriteLine(result);

To apply a method you would call the same InvokeMember function with the BindingFlags.InvokeMethod and add optional method arguments to the last argument like this:

object result = (object)type.InvokeMember("ToString", BindingFlags.InvokeMethod, null, inst, new object[]{ "string" });

Keep an eye out for .net core 3.0 that advertises native support for dynamic method calling like you see in Python https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-0#interop-improvements

pastaleg
  • 1,782
  • 2
  • 17
  • 23