【问题标题】:C# MSScriptControl Pass Class to FunctionC# MSScriptControl 将类传递给函数
【发布时间】:2017-10-04 22:58:36
【问题描述】:

我在 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)中获取数据。我尝试了here 提供的技术,但它不起作用:

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。

【问题讨论】:

  • 您需要从 System.Runtime.InteropServices 获取 ITypeInfo,而不是使用 System.Reflection:

标签: c# msscriptcontrol


【解决方案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# 中我的脚仍然湿透了。

【讨论】:

    【解决方案2】:

    自从引入dynamic 以来,可以将COM 对象视为动态,在您的示例中,您可以简单地这样做:

    dynamic fx = scriptControl.Run("youFunction");
    string name = fx.name;
    

    【讨论】:

      【解决方案3】:
      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); 
          }
      } 
      

      【讨论】:

      • 谢谢。这没有做我需要的,但让我朝着正确的方向前进。
      猜你喜欢
      • 1970-01-01
      • 2015-02-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-01
      • 1970-01-01
      • 2018-05-09
      • 2014-04-03
      • 1970-01-01
      相关资源
      最近更新 更多