2

我在 C# 中使用 MSScriptControl。我想将一个类从脚本传递给主机。简化示例: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
    }
}

我的问题是:如何从对象中获取数据(C# 报告为 System.__ComObject)。我尝试了这里提供的技术,但它不起作用:

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 为 0。

4

3 回答 3

1

建立在 Mangist 的代码之上,这是可行的:

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;
        }
    }
}

我以前在 C++ 中做过这个,所以我可以复制代码,但我仍然在 C# 中弄湿了我的脚。

于 2012-06-26T18:12:45.573 回答
1

由于引入了动态,可以将COM对象视为动态,在您的示例中,您可以简单地执行以下操作:

dynamic fx = scriptControl.Run("youFunction");
string name = fx.name;
于 2015-03-25T14:03:46.747 回答
0
using System; 
using System.Runtime.InteropServices; 
using ComTypes = System.Runtime.InteropServices.ComTypes; 

namespace ComUtils 
{ 
    public class ComHelper 
    { 
        /// <summary> 
        /// Returns a string value representing the type name of the specified COM object. 
        /// </summary> 
        /// <param name="comObj">A COM object the type name of which to return.</param> 
        /// <returns>A string containing the type name.</returns> 
        public static string GetTypeName(object comObj) 
        { 

            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; 

            ComTypes.ITypeInfo typeInfo = null; 
            try 
            { 
                try 
                { 
                    // obtain the ITypeInfo interface from the object 
                    dispatch.GetTypeInfo(0, 0, out typeInfo); 
                } 
                catch (Exception ex) 
                { 
                    //Cannot get the ITypeInfo interface for the specified COM object 
                    return String.Empty; 
                } 

                string typeName = ""; 
                string documentation, helpFile; 
                int helpContext = -1; 

                try 
                { 
                    //retrieves the documentation string for the specified type description 
                    typeInfo.GetDocumentation(-1, out typeName, out documentation, 
                        out helpContext, out helpFile); 
                } 
                catch (Exception ex) 
                { 
                    // Cannot extract ITypeInfo information 
                    return String.Empty; 
                } 
                return typeName; 
            } 
            catch (Exception ex) 
            { 
                // Unexpected error 
                return String.Empty; 
            } 
            finally 
            { 
                if (typeInfo != null) Marshal.ReleaseComObject(typeInfo); 
            } 
        } 
    } 

    /// <summary> 
    /// Exposes objects, methods and properties to programming tools and other 
    /// applications that support Automation. 
    /// </summary> 
    [ComImport()] 
    [Guid("00020400-0000-0000-C000-000000000046")] 
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    interface IDispatch 
    { 
        [PreserveSig] 
        int GetTypeInfoCount(out int Count); 

        [PreserveSig] 
        int GetTypeInfo( 
            [MarshalAs(UnmanagedType.U4)] int iTInfo, 
            [MarshalAs(UnmanagedType.U4)] int lcid, 
            out ComTypes.ITypeInfo typeInfo); 

        [PreserveSig] 
        int GetIDsOfNames( 
            ref Guid riid, 
            [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] 
            string[] rgsNames, 
            int cNames, 
            int lcid, 
            [MarshalAs(UnmanagedType.LPArray)] int[] rgDispId); 

        [PreserveSig] 
        int Invoke( 
            int dispIdMember, 
            ref Guid riid, 
            uint lcid, 
            ushort wFlags, 
            ref ComTypes.DISPPARAMS pDispParams, 
            out object pVarResult, 
            ref ComTypes.EXCEPINFO pExcepInfo, 
            IntPtr[] pArgErr); 
    }
} 
于 2012-06-26T16:44:14.820 回答