在C#中创建COM / ActiveXObject的,从JScript中使用,具有简单的事件(Cre

2019-06-25 17:30发布

我想C#创建一个COM对象,并通过IDispatch接口从JScript中使用它。 这部分非常简单。

我也想实现COM对象的简单的回调,类似于XmlHttpRequest对象是在浏览器中使用的暴露事件。 这种模式允许JavaScript附加事件处理程序是这样的:

var xmlhttp = new ActiveXObject("MSXML.XMLHTTP"); 
xmlhttp.onReadyStateChange = function() {
  ...
};

我希望我的客户端JScript代码看起来像这样:

var myObject = new ActiveXObject("MyObject.ProgId");
myObject.onMyCustomEvent = function(..args here..) { 
   ...
};

什么是C#代码样子的? 我想一般的情况下 - 我希望能够通过参数发送回给Javascript FN。


我已经看到了我如何才能在JavaScript中C#引发事件写了一个ActiveX控件,点击时? ,但答案有看起来很复杂,实施和复杂的使用。


从这篇文章中 ,似乎XMLHttpRequest的事件不是COM事件。 该onreadystatechange是类型的属性IDispatch 。 当客户端脚本设置该属性的功能,JScript的老帅它作为一个IDispatch对象。

剩下唯一的问题是,然后调用从C#IDispatch的。

Answer 1:

由于它是COM,通过定义一个接口开始。 让我们保持它的简单。

[Guid("a5ee0756-0cbb-4cf1-9a9c-509407d5eed6")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IGreet
{
    [DispId(1)]
    string Hello(string name);

    [DispId(2)]
    Object onHello { get; set; }
}

随后,执行:

[ProgId("Cheeso.Greet")]
[ComVisible(true)]
[Guid("bebcfaff-d2f4-4447-ac9f-91bf63b770d8")]
[ClassInterface(ClassInterfaceType.None)]
public partial class Greet : IGreet
{
    public Object onHello { get; set; }

    public String Hello(string name)
    {
        var r = FireEvent();
        return "Why, Hello, " + name + "!!!" + r;
    }
}

主要的窍门是FireEvent方法。 这为我工作。

    private string FireEvent()
    {
        if (onHello == null) return " (N/A)";
        onHello
            .GetType()
            .InvokeMember
            ("",
             BindingFlags.InvokeMethod,
             null,
             onHello,
             new object [] {});

        return "ok";
    }

编译所有的在一起,regasm注册它:

%NET64%\regasm.exe Cheeso.Greet.dll /register /codebase

...然后用它从JScript中是这样的:

var greet = new ActiveXObject("Cheeso.Greet"), response;
greet.onHello = function() {
    WScript.Echo("onHello (Javascript) invoked.");
};
response = greet.Hello("Fred");
WScript.Echo("response: " + response);

有用。

您也可以从VBScript调用它:

Sub onHello ()
    WScript.Echo("onHello (VBScript) invoked.")
End Sub

Dim greet
Set greet = WScript.CreateObject("Cheeso.Greet")
greet.onHello = GetRef("onHello")
Dim response
response = greet.Hello("Louise")
WScript.Echo("response: " &  response)

从C#参数传递回JScript中使用这种方法,我认为对象需要是IDispatch接口,当然你可以发送回编组为字符串,整数,等其上封你所期望的简单值。

例如,修改的C#代码到参考送回其自身,并且数量42。

        onHello
            .GetType()
            .InvokeMember
            ("",
             BindingFlags.InvokeMethod,
             null,
             onHello,
             new object [] { this, 42 });

然后,你可以在像这样的JScript:

greet.onHello = function(arg, num) {
    WScript.Echo("onHello (Javascript) invoked.");
    WScript.Echo("  num = " + num + "  stat=" + arg.status);
};

或在VBScript像这样:

Sub onHello (obj, num)
    WScript.Echo("onHello (VBScript) invoked. status=" & obj.status )
    WScript.Echo("  num= " & num)
End Sub

注意:你可以定义你的JScript事件处理函数接受比由C#对象调用“事件”时,发送较少ARGS。 根据我的经验,你需要设计VBScript中的事件处理程序,明确接受正确的参数个数。



Answer 2:

哇,哇! 可能很容易?

using System;
using System.EnterpriseServices;

[assembly: ApplicationName("Calculator")]
[assembly: ApplicationActivation(ActivationOption.Library)]
public class Calculator : ServicedComponent
{
    public int Add(int x, int y){ return (x + y); }
}

然后使用这些构建命令

 sn -k Calculator.snk           
 csc /t:library Calculator.cs
 regsvcs Calculator.dll

在JScript中(WSH):

c = new ActiveXObject("Calculator");
WScript.Echo(typeof(c));  // output: object
WScript.Echo(c.Add(4,1)); // output: 5

来源: MSDN

请享用!



文章来源: Create COM/ActiveXObject in C#, use from JScript, with simple event