DOBON.NETプログラミング道掲示板
(現在 過去ログ1 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■33246 / inTopicNo.1)  C# 製COMをJavaScriptから使う時のイベントフック
  
□投稿者/ ぺんたごん 一般人(16回)-(2016/02/18(Thu) 22:09:26)
  • アイコン環境/言語:[C#/.NET 4.5.1] 
    分類:[.NET] 

    お久しぶりです。
    今回、ビジネス的な圧力により、他社製Webアプリから
    自社C#製アプリと連携する必要が出てきました。
    
    こちら側にCOMインタフェースを備えregasmし、JavaScriptでnew ActiveXObjectして
    メソッドを呼び出したりプロパティを参照したり
    設定したり…までは出来ました。
    しかし、COM側からのイベントをJSでフックする方法がわかっていません。
    
    イベント名をCallbackとすると、IE11のF12ツールでオブジェクトを確認すると「add_Callback」「remove_Callback」というメソッドが自動で出来ているのが見えたので、
    これをなんとかすればいけるかなと思い
    _obj.add_Callback(function(){
      alert('ほげ');
    });
    と試してみたのですがクラスはオートメーション云々と言われます。
    ググっても、C++製のちゃんとしたActiveXとの連携しか
    情報が出てこないので困り果ててます。
    
    どなたかご教示いただければ助かります…

引用返信 削除キー/
■33247 / inTopicNo.2)  Re[1]: C# 製COMをJavaScriptから使う時のイベントフック
□投稿者/ Hongliang 大御所(510回)-(2016/02/18(Thu) 22:39:32)
  • アイコンC#がCOMサーバ側と言うことですね。
    C#側はこんな感じにします。
    https://msdn.microsoft.com/ja-jp/library/dd8bf0x3.aspx
    JavaScript側は「C++製のちゃんとしたActiveXとの連携」と同じで問題ないはずです。
引用返信 削除キー/
■33249 / inTopicNo.3)  Re[1]: C# 製COMをJavaScriptから使う時のイベントフック
□投稿者/ kiku 一般人(4回)-(2016/02/19(Fri) 17:59:49)
  • アイコン自身で検証したことはありませんが
    わかりやすく説明しているブログを見つけたので貼っておきます。

    http://qiita.com/tomochan154/items/1ce33f2aef167c0fed9d

引用返信 削除キー/
■33250 / inTopicNo.4)  Re[2]: C# 製COMをJavaScriptから使う時のイベントフック
□投稿者/ ぺんたごん 一般人(17回)-(2016/02/19(Fri) 21:35:38)
  • アイコン
    No33249に返信(kikuさんの記事)
    > 自身で検証したことはありませんが
    > わかりやすく説明しているブログを見つけたので貼っておきます。
    > 
    > http://qiita.com/tomochan154/items/1ce33f2aef167c0fed9d
    > 
    
    ありがとうございます。
    職場から書けなくて遅くなりました。
    
    提示頂いた内容は、実はもう実装していて、Excel VBAで参照設定した場合にちゃんと動いてます。
    今回肝心なところは、HTMLに一切の変更を加えずにJavaScript内だけでイベントフックする方法でした。
    ググると、HTMLでobjectタグ使って生成してscriptのfor、event属性でフックする方法が
    大量に出てきてたのですが、new ActiveXObject('hoge.piyo')で生成したオブジェクトに対して
    C#で言う +=、VBでいうAddHandler的な何かがないかな、という点でした。
    
    IE11のF12ツールでオブジェクトをウォッチすると、C#で追加した覚えの無い
    add_XXX、remove_XXXというメソッドがあったのでどう使うのかなーと試行錯誤していたのですが
    結局別の方法で解決しました。
    
    var _obj;
    
    function ApplicationStart() {
      _obj = new ActiveXObject('hoge.piyo');
      eval('function _obj::Callback() { onCallback(); }');  //ここでイベントハンドラ紐付け
      _obj.Startup();  // C#側で用意したメソッド
    }
    
    function onCallback() {
      alert('いぇーい');
    }
    
    
    ただ、add_XXX、remove_XXXの使い方を御存知の方は情報をお待ちしてます。
    evalで文字列ベッタベターな書き方は個人的に好まないので…

引用返信 削除キー/
■33251 / inTopicNo.5)  Re[3]: C# 製COMをJavaScriptから使う時のイベントフック
□投稿者/ 魔界の仮面弁士 大御所(1004回)-(2016/02/19(Fri) 21:49:30)
  • アイコンNo33250に返信(ぺんたごんさんの記事)
    > 大量に出てきてたのですが、new ActiveXObject('hoge.piyo')で生成したオブジェクトに対して
    > C#で言う +=、VBでいうAddHandler的な何かがないかな、という点でした。
    VBScript でいうところの GetRef 実装で良ければ、
    オブジェクトの既定メンバー(DispId=0)を動的呼び出しすれば
    コールバックできたと思います。一般的な手法かどうかは別として。

    > add_XXX、remove_XXXというメソッドがあったので
    add_EventName は JScript.NET におけるイベント割り当て手法ですね。
    C# との連携は試したことが無いですが、JSciprt.NET で exe を
    作っていた時には、この方法を用いていました。
    https://msdn.microsoft.com/ja-jp/library/06t47502.aspx

    HTML から利用する場合は、COM オブジェクトの有効期間にも注意。
    https://msdn.microsoft.com/ja-jp/library/dn741342.aspx
引用返信 削除キー/
■33252 / inTopicNo.6)  Re[4]: C# 製COMをJavaScriptから使う時のイベントフック
□投稿者/ ぺんたごん 一般人(18回)-(2016/02/20(Sat) 09:18:43)
  • アイコンNo33251に返信(魔界の仮面弁士さんの記事)
    > ■No33250に返信(ぺんたごんさんの記事)
    >>大量に出てきてたのですが、new ActiveXObject('hoge.piyo')で生成したオブジェクトに対して
    >>C#で言う +=、VBでいうAddHandler的な何かがないかな、という点でした。
    > VBScript でいうところの GetRef 実装で良ければ、
    > オブジェクトの既定メンバー(DispId=0)を動的呼び出しすれば
    > コールバックできたと思います。一般的な手法かどうかは別として。
    >
    >>add_XXX、remove_XXXというメソッドがあったので
    > add_EventName は JScript.NET におけるイベント割り当て手法ですね。
    > C# との連携は試したことが無いですが、JSciprt.NET で exe を
    > 作っていた時には、この方法を用いていました。
    > https://msdn.microsoft.com/ja-jp/library/06t47502.aspx
    >
    > HTML から利用する場合は、COM オブジェクトの有効期間にも注意。
    > https://msdn.microsoft.com/ja-jp/library/dn741342.aspx

    ありがとうございます。
    なるほど、add_とremove_はJScript.NET用ですか…
    今回は無関係そうですね。一応後学のために見ておきます。
    (連携元のWebアプリ側は他社製なので…)

    COMの有効期間について「HTMLから利用する場合」というのは、
    HTMLのタグ記述やDOMを使わずJS内だけで完結してる今回のやり方には
    該当しないと思っていますが認識はあっていますか?

    提示していただいた情報先を見るとdocument使ってるのと、
    「DOM要素またはオブジェクト」が「イベントリスナー」と異なる有効期間の場合、とあるので、
    今回は1js内でオブジェクトもイベントハンドラも扱ってるので
    大丈夫なのかなと思っていますが
引用返信 削除キー/
■33255 / inTopicNo.7)  Re[3]: C# 製COMをJavaScriptから使う時のイベントフック
□投稿者/ 魔界の仮面弁士 大御所(1007回)-(2016/02/22(Mon) 04:04:05)
  • アイコン
    No33250に返信(ぺんたごんさんの記事)
    > scriptのfor、event属性でフックする方法が大量に出てきてたのですが
    VBA で参照設定 + WithEvents した場合に相当するのがその記述です。
    実装する場合は ComSourceInterfacesAttribute ですね。
    
    
    > C#で言う +=、VBでいうAddHandler的な何かがないかな、という点でした。
    VBA や VBScript、JScript にはそのための仕組みがないので、
    遅延バインディングにしたいなら、自前で用意しないと駄目でしょうね。
    
    無いのなら
    作ってしまえ
    ホトトギス
    
    
    ―――ということで、
     _obj.AttachEvent( "callback", onCallback  ) ;
    のように、関数オブジェクトを受け取るメンバーを作ってみました。
    (簡略化のため、C# や VBA から使うための event 実装は省略しています)
    
    
    CD /D C:\SAMPLE\20160222\
    csc Orator.Sample.cs /t:library /platform:AnyCPU /out:Orator.Sample.dll
    regasm /codebase Orator.Sample.dll /tlb:Orator.Sample.tlb
    
    
    
    【Orator.Sample.cs】
    using System.Runtime.InteropServices;
    using System.Collections.Generic;
    [assembly: ComVisible(true)]
    namespace Orator
    {
        // JScript の関数オブジェクト用
        [ComVisible(false)]
        public delegate object Function(object sender, params object[] args);
    
    
        [ComVisible(true)]
        [ProgId("Orator.Sample")]
        [Guid("A17FC5F2-0EC7-4A8F-A648-9075E5976359")]
        [ClassInterface(ClassInterfaceType.None)]
        [ComDefaultInterface(typeof(Orator.ISample))]
        public sealed class Sample : ISample
        {
            // JScript はイベント呼び出しの構文を備えていないので、
            // 関数オブジェクトを受け取ってコールバックさせる
            private Dictionary<string, Function> events;
            public Sample()
            {
                events = new Dictionary<string, Function>();
                events.Add("NameChanging", null);
                events.Add("NameChanged", null);
            }
    
            #region AttachEvent メソッド
            void ISample.AttachEvent(string eventName, object functionObject)
            {
                // 関数オブジェクトをイベントハンドラとして割り当て
                events[eventName] += new Function((caller, args) =>
                    // 関数オブジェクトの実行
                    functionObject.GetType().InvokeMember(
                        "[DispID=0]",
                        System.Reflection.BindingFlags.InvokeMethod,
                        System.Type.DefaultBinder,
                        functionObject,
                        args
                    )
                );
            }
            #endregion
    
            #region Name プロパティ
            private string name = "Sample";
            string ISample.Name
            {
                get { return name; }
                set
                {
                    string oldName = name;
                    string newName = value;
                    if (oldName != newName)
                    {
                        if (events["NameChanging"] != null)
                        {
                            events["NameChanging"](this, oldName, newName);
                        }
                        name = value;
                        if (events["NameChanged"] != null)
                        {
                            events["NameChanged"](this);
                        }
                    }
                }
            }
            #endregion
        }
    
        #region COMオブジェクトのメンバー定義
        [Guid("02A9900A-EB12-4189-B8FF-396CF80EF78A")]
        public interface ISample
        {
            // JScript の関数オブジェクトや、VBScript の GetRef を
            // イベントに割り当てるためのヘルパー
            void AttachEvent(string eventName, object functionObject);
    
            // Name プロパティ
            string Name { get; set; }
        }
        #endregion
    }
    
    
    
    【Orator.Sample.hta】
    <html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9" />
    <title>Sample</title>
    <script language="JScript">
    var _obj;
    window.onload = function()
    {
      window.resizeTo(400, 250);
      _obj = new ActiveXObject("Orator.Sample");
      text1.value = _obj.Name;
    
      _obj.AttachEvent("NameChanging", fnNameChanging ) ;
      _obj.AttachEvent("NameChanged", fnNameChanged ) ;
    
      button1.onclick = function()
      {
        if(_obj.Name != text1.value)
        {
          _obj.Name = text1.value;
        }
        else
        {
          alert("元のNameと同じです");
        }
      };
    }
    
    function fnNameChanging(oldName, newName)
    {
        alert("NameChanging:\r\n" + oldName + " => " + newName);
    }
    
    function fnNameChanged()
    {
        alert("NameChanged");
    }
    
    </script>
    <hta:application border="dialog" contextmenu="no" scroll="no" selection="no" singleInstance="yes">
    </head>
    <body style="background-color:ButtonFace;color:ButtonText">
    <p>
    <input type="text" id="text1" value="undefined">
    <input type="button" id="button1" value="set">
    </p>
    </body></html>

引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -