我在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。
答案 0 :(得分: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#中沾沾自喜。
答案 1 :(得分:1)
自dynamic引入以来,可以将COM
对象视为动态,在您的示例中,您可以简单地执行:
dynamic fx = scriptControl.Run("youFunction");
string name = fx.name;
答案 2 :(得分: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);
}
}