Create COM/ActiveXObject in C#, use from JScript, with simple event

前端 未结 2 1251
有刺的猬
有刺的猬 2020-12-10 06:10

I\'d like to create a COM object in C#, and use it via IDispatch from JScript. That part is pretty simple.

I also want to implement simple callbacks on the COM objec

相关标签:
2条回答
  • 2020-12-10 06:18

    Wow, wow! May be easy?

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

    then use these build command

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

    On jscript (wsh):

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

    source: msdn

    Enjoy!

    0 讨论(0)
  • 2020-12-10 06:32

    Since it's COM, start by defining an interface. Let's keep it simple.

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

    Then, the implementation:

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

    The main trick is the FireEvent method. This worked for me.

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

    Compile that all together, register it with regasm:

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

    ...And then use it from JScript like this:

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

    It works.

    You can also call it from 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)
    

    To pass parameters back from C# to JScript with this approach, I think objects need to be IDispatch, but of course you can send back simple values marshaled as string, int, and so on which are marshaled as you would expect.

    For example, modify the C# code to send back a reference to itself, and the number 42.

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

    Then, you can get that in jscript like so:

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

    Or in VBScript like so:

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

    NB: You can define your jscript event handler function to accept fewer args than are sent by the C# object when invoking the "event". In my experience you need to design the event handler in VBScript to explicitly accept the correct number of arguments.

    0 讨论(0)
提交回复
热议问题