Javascript 在JScript中:我可以枚举通过新ActiveXObject()创建的对象上的方法吗?

Javascript 在JScript中:我可以枚举通过新ActiveXObject()创建的对象上的方法吗?,javascript,activexobject,Javascript,Activexobject,对于Eric Lippert或熟悉JScript引擎实现的Microsoft人员来说,这确实是一个问题 我可以这样做吗: var obj = new ActiveXObject("My.ProgId"); var methods = GetMethodsViaMagic(obj); ? (假设COM类型支持IDispatch) 如果是的话,getMethodsVimagic()看起来像什么 EDIT-当然,我尝试的第一件事是for…in循环,但这不适用于ActiveX对象上定义的方法和属性。

对于Eric Lippert或熟悉JScript引擎实现的Microsoft人员来说,这确实是一个问题

我可以这样做吗:

var obj = new ActiveXObject("My.ProgId");
var methods = GetMethodsViaMagic(obj);
?

(假设COM类型支持IDispatch)

如果是的话,
getMethodsVimagic()
看起来像什么


EDIT-当然,我尝试的第一件事是
for…in
循环,但这不适用于ActiveX对象上定义的方法和属性。至少,对于我在.NET中定义并通过
ComVisible
公开的对象是不允许的


在C#中,我可以这样定义IDispatch:

 [Guid("00020400-0000-0000-c000-000000000046"),
  InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
 public interface IDispatch
 {
     int GetTypeInfoCount();
     System.Runtime.InteropServices.ComTypes.ITypeInfo
         GetTypeInfo([MarshalAs(UnmanagedType.U4)] int iTInfo,
                     [MarshalAs(UnmanagedType.U4)] int lcid);

     [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,
                [MarshalAs(UnmanagedType.U4)] int lcid,
                [MarshalAs(UnmanagedType.U4)] int dwFlags,
                ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
                [Out, MarshalAs(UnmanagedType.LPArray)] object[] pVarResult,
                ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
                [Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] pArgErr);
 }
    var idispatch = (IDispatch) comObject ;
    System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo =
        idispatch.GetTypeInfo(0, 0);

    System.Runtime.InteropServices.ComTypes.FUNCDESC funcDesc;
    string strName, strDocString, strHelpFile;
    int dwHelpContext;

    typeInfo.GetFuncDesc(i, out pFuncDesc);// i = 1, 2, 3...
    funcDesc = (System.Runtime.InteropServices.ComTypes.FUNCDESC)
        Marshal.PtrToStructure(pFuncDesc,
                               typeof(System.Runtime.InteropServices.ComTypes.FUNCDESC));
然后我可以这样做:

 [Guid("00020400-0000-0000-c000-000000000046"),
  InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
 public interface IDispatch
 {
     int GetTypeInfoCount();
     System.Runtime.InteropServices.ComTypes.ITypeInfo
         GetTypeInfo([MarshalAs(UnmanagedType.U4)] int iTInfo,
                     [MarshalAs(UnmanagedType.U4)] int lcid);

     [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,
                [MarshalAs(UnmanagedType.U4)] int lcid,
                [MarshalAs(UnmanagedType.U4)] int dwFlags,
                ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
                [Out, MarshalAs(UnmanagedType.LPArray)] object[] pVarResult,
                ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
                [Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] pArgErr);
 }
    var idispatch = (IDispatch) comObject ;
    System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo =
        idispatch.GetTypeInfo(0, 0);

    System.Runtime.InteropServices.ComTypes.FUNCDESC funcDesc;
    string strName, strDocString, strHelpFile;
    int dwHelpContext;

    typeInfo.GetFuncDesc(i, out pFuncDesc);// i = 1, 2, 3...
    funcDesc = (System.Runtime.InteropServices.ComTypes.FUNCDESC)
        Marshal.PtrToStructure(pFuncDesc,
                               typeof(System.Runtime.InteropServices.ComTypes.FUNCDESC));
…并获取函数(方法)名称和参数数等


对于ActiveX(COM IDispatch)对象,我可以在JScript中执行类似的操作吗?

您应该可以这样做

var methods = [];
for( var property in obj ) {
    if( obj.hasOwnProperty(property) && typeof obj[property] === 'function' ) {
        methods.push(property);
    }
}
方法
数组将包含方法名称。如果所讨论的对象是某个构造函数的实例,您可能需要删除
hasOwnProperty
检查,因为这将所有内容限制为只查看在obj本身上定义的属性/方法,而不是其原型链中定义的属性/方法

至于参数的数量,您可以使用函数本身(正如Domenic在注释中指出的那样)

因此,要获取
obj
中每个方法的名称和参数数量:

var methods = [];
for( var property in obj ) {
    if( obj.hasOwnProperty(property) && typeof obj[property] === 'function' ) {
        methods.push({
            name: property,
            args: obj[property].length
        });
    }
}
您将获得一个对象文本数组,每个文本包含
obj
中方法的名称和参数数量


编辑:当我第一次写这个答案时,我正在考虑获取参数的名称(而不仅仅是数量),因此包含了一些相当粗糙的代码来获取这些名称。如果有人感兴趣,下面是代码,我只是无耻地从中盗取)


将一个函数/方法传递给该函数,它将返回参数名称…也许。如果返回的对象是一个完全成熟的宿主对象,则其方法/函数可能无法被
toString()
读取。通常,
toString()
将返回方法/函数的实际源代码(并且
argumentNames
函数使用一些正则表达式解析),但对于本机代码,您可能只会返回字符串“本机代码”或其他内容,而不是源代码。

我发现,如果我在ComVisible.NET对象上实现了DirectReflect,我可以使用Javascript
for…in
循环来枚举方法和属性


作为《特定常规武器公约》的IDispatch进行编组

首先,请记住,我已经十多年没有使用JScript了;那时候发动机已经换了,我的记忆也消失了

据我记忆和知识所及:如果对象实现IDispatchEx,for in循环将起作用,但如果对象仅实现IDispatch,则不会起作用


我一直想添加一种机制,使JScript程序可以使用与dispatch对象关联的类型信息中的可用信息来枚举属性,但是我不相信我真的写过代码。

你可以通过函数对象的
length
属性来获得函数的参数数量:Domenic:当然,你是对的-我考虑参数名称是出于某种原因。我会更新我的答案。谢谢期待微软的ActiveX对象实现Netscape的JavaScript或ECMAScript的功能是一个漫长的过程。不要惊讶它失败或抛出错误。@RobG:没错……但是在-循环中使用
for…获取方法名应该是可行的。但是,是的,我不知道其他的东西…弗拉米诺和罗布:哎呀,我写问题的时候累了。我应该提到,我在
循环中尝试了..的
,但它不适用于COM对象。感谢您的贡献,Lippert先生。拥有您描述的功能会很方便。无法想象现在添加该功能会破坏许多程序。我知道Win8越来越受Javascript的喜爱;看起来很有趣,但事实并非如此。
for..in
循环不适用于com可见的、基于DirectReflect的类。唯一的原因似乎是埃里克的答案上面;也就是说,它需要一个IDispatchEx接口(而IReflect只实现IDispatch,如链接中所述)。