Search code examples
c#msscriptcontrol

C# MSScriptControl Pass Class to Function


I am using MSScriptControl in C#. I would like to pass a class from the script to the host. Simplified example: Javascript:

function Fx(n) {
    this.name = n;
}
var fx = new Fx("test");
rfx.DoEffect(fx);

C#:

[ComVisible(true)]
public class Rfx {
    public void DoEffect(object fx) {
        // Try to read fx.name
    }
}

My question is: How do I get the data out of the object (which C# reports as System.__ComObject). I tried the technique offered here, but it doesn't work:

public void DoEffect(object fx)
{
    System.Reflection.FieldInfo[] myFields = fx.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
    Console.WriteLine("FieldInfo length = " + myFields.Length);
    for (int i = 0; i < myFields.Length; i++)
    {
         Console.WriteLine("The value of {0} is: {1}", myFields[i].Name, myFields[i].GetValue(fx));
    }
}

myFields.Length is 0.


Solution

  • Building off Mangist's code, this works:

    using System; 
    using System.Runtime.InteropServices; 
    using ComTypes = System.Runtime.InteropServices.ComTypes;
    
    public class ComHelper 
    {
        public static string GetValue(object comObj, string name)
        {
            if (comObj == null)
                return String.Empty;
    
            if (!Marshal.IsComObject(comObj))
                //The specified object is not a COM object 
                return String.Empty;
    
            IDispatch dispatch = comObj as IDispatch;
            if (dispatch == null)
                //The specified COM object doesn't support getting type information 
                return String.Empty; 
    
            try
            {
                int language_id = 0;
                int DISPATCH_METHOD = 0x1;
                int DISPATCH_PROPERTYGET = 0x2;
    
                int[] displayIDs = new int[1];
                Guid empty = Guid.Empty;
                string[] names = new string[] { name };
                dispatch.GetIDsOfNames(ref empty, names, names.Length, language_id, displayIDs);
                System.Runtime.InteropServices.ComTypes.DISPPARAMS dspp = new System.Runtime.InteropServices.ComTypes.DISPPARAMS();
                System.Runtime.InteropServices.ComTypes.EXCEPINFO ei = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();
                IntPtr[] arg_err = new IntPtr[10];
                object result;
                if (1 == displayIDs.Length)
                {
                    dispatch.Invoke(displayIDs[0], ref empty, language_id, (ushort)(DISPATCH_METHOD | DISPATCH_PROPERTYGET), ref dspp, out result, ref ei, arg_err);
                    return result.ToString();
                }
                return String.Empty;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return String.Empty;
            }
        }
    }
    

    I had done this previously in C++ so I could copy the code over, but am still getting my feet wet in C#.