最新の更新情報

 
このブログ「吟遊詩人の戯言」 の記事検索...

C#での自PC内プロセス間通信

関連記事

またまた,必要に迫られて実装をば...

最初,Localhostに対して,ソケットで通信しようかと思いましたが…
Net Frameworkに,便利なクラスが追加されているそうで

    IpcServerChannelクラス
    IpcClientChannelクラス

を使えば,さくっとプロセス間通信,実装できましたです

なお,こちらのページを参考にしました
あわせて,御確認ください

[C#][Program]C# .NETリモーティングを使ったプロセス間通信@tetsuarossa
[C#][Program]C# .NETリモーティングを使ったプロセス間通信 その2@tetsuarossa

tetsuarossaさま,サンクスです 🙂




【追記:09/04/15】

ここに記載したコード,サンプルプロジェクトとして,丸ごとアップしておきます
ダウンロードは,こちら@C#
ご自由にお使いくださいませ!

なお,バグってたら,すまんでごわす :mrgreen:




1.System.Runtime.Remotingを参照設定(サーバ側クライアント側両方で,です)
2.下記コードを Using追加する(サーバ側クライアント側両方で,です)
なお,RemoteTranceObjectネームスペースが情報共有クラスとなります
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;
using RemoteTranceObject;

3.情報共有を行うRemoteTranceObjectネームスペースの定義
サーバー,クライアント,同一の定義が必要です.
この部分だけ,クラスDLLにして,参照設定しちゃうほうが,あとあと管理が楽かも?
今回は制御モード(int)と,怪しい文字列(string)をクライアント側からサーバ側へ伝送させます
namespace RemoteTranceObject  //共有オブジェクト(サーバー/クライアントで全く同一内容で定義してください)
{
    public class ClassFileInfo : MarshalByRefObject
    {
        public class ClassFileInfoEventArg : EventArgs            //情報を引き渡すイベント引数クラス
        {
            private int m_mode = 0;                    //モード
            private string m_FileName = "";            //文字列

            public int Mode { get { return m_mode; } set {m_mode = value;}}
            public string FileName { get { return m_FileName; } set {m_FileName = value;}}

            public ClassFileInfoEventArg(int tmpMode, string tmpfName)
            {
                m_mode = tmpMode;
                m_FileName = tmpfName;
            }
        }

        public delegate void CallEventHandler(ClassFileInfoEventArg e);
        public event CallEventHandler OnTrance;
            
        public void DataTrance(int tmpmode, string tmpfname)
        {
            if (OnTrance != null)
            {
                OnTrance(new ClassFileInfoEventArg(tmpmode, tmpfname));
            }
        }
        
    }
}

4.サーバー側の実装
普通のWindowsフォームアプリのプロジェクト作って
ラベル1個と,リストボックス1個を貼り付けました
クライアントから送られてきた情報は,リストボックスに追加されていきます
namespace ProTestServer
{
    public partial class Form1 : Form
    {
        private ClassFileInfo m_msg;

        //コンストラクタ
        public Form1()
        {
            InitializeComponent();
        }

        //フォームロード
        private void Form1_Load(object sender, EventArgs e)
        {
            //このチャネル生成系は一度通せばいいっぽい

            // IPC Channelを作成
            IpcServerChannel servChannel = new IpcServerChannel("processtrancetest");
            
            // リモートオブジェクトを登録
            ChannelServices.RegisterChannel(servChannel, true);

            //// ChannelのURIを表示
            label1.Text = servChannel.GetChannelUri();

            // イベントを登録
            m_msg = new ClassFileInfo();

            m_msg.OnTrance += new ClassFileInfo.CallEventHandler(m_msg_OnTrance);

            RemotingServices.Marshal(m_msg, "message", typeof(ClassFileInfo));
        }

        //クライアントから転送されてきた情報をリストボックスに表示
        void m_msg_OnTrance(ClassFileInfo.ClassFileInfoEventArg e)
        {
            string st;

            switch(e.Mode)
            {
                case 1:
                    st = "モード1";
                    break;
                case 2:
                    st = "モード2";
                    break;
                case 3:
                    st = "モード3";
                    break;
                default:
                    st = "???";
                    break;
            }


            listBox1.Items.Add(st + " , " + e.FileName);
        }
    }
}

5.クライアント側の実装 こちらも普通のWindowsフォームアプリにて
ラジオボタン3つ,テキストボックス1個,ボタン1個を貼り付けてください
ボタンを押すたびに,サーバ側へ情報伝送します
あと,3つのラジオボタンのTagプロパティに1~3の数値を設定してあります
namespace ProTestClient
{
    public partial class Form1 : Form
    {
        private int m_mode;
        private ClassFileInfo m_msg = null;

        //コンストラクタ
        public Form1()
        {
            InitializeComponent();

            m_mode = 1;
        }

        //フォームロード
        private void Form1_Load(object sender, EventArgs e)
        {
            //このチャネル生成系は一度通せばいいっぽい
            
            // IPC Channel を作成
            IpcClientChannel clientChannel = new IpcClientChannel();

            // リモートオブジェクトを登録
            ChannelServices.RegisterChannel(clientChannel, true);

            // オブジェクトを作成
            m_msg = (ClassFileInfo)Activator.GetObject(typeof (ClassFileInfo), "ipc://processtrancetest/message");

        }

        //ラジオボタンでモードを設定
        private void rdbClick(object sender, EventArgs e)
        {

            string st = (sender as RadioButton).Tag as string;

            m_mode = int.Parse(st);

        }

        //ボタンを押すたびに,モードと入力文字をサーバ側へ送信
        private void button1_Click(object sender, EventArgs e)
        {
            string st = textBox1.Text;

            if (st == "")
            {
                st = "空文字";
            }

            m_msg.DataTrance(m_mode, st);                //サーバーへ伝送
        }

    }
}

クライアント側 ClassFileInfo.DataTrance() を呼び出すたびに
サーバ側で,デリゲートが呼び出される仕組みです

情報共有クラスにプロパティを追加すれば
サーバ側で,設定した値をクライアントでも,読み出せるはず,です(汗

また,私自身がどこかで使うかもしれないので
ここに記載しておきますです…


 
 
 
 

12 comments to C#での自PC内プロセス間通信

  • 通りすがり

    ありがとうございました。とても参考になりました。 😉
    なかなか form 形式での sample が見つからなかったので。
    蛇足かもしれませんが 2 の所の using System.Runtime.Remoting の部分で、ソリューションエクスプローラで各 exe の参照設定に System.Runtime.Remotingを追加しないと私の場合ビルドエラーになってしまいました。
    重ねてありがとうございます。参考になりました。

  • >>通りすがり さま

    ようこそ!
    参考になったみたいで,よかったです

    参照設定の件,(1)にちょろっと,書いてありますです
    見落とされたかな?? 😉


    また,面白そうなコードが出てきたら,ここに記載していきますです 🙂

  • たけぞ

    Tag値のとり方がわからず、ここへたどり着きました。ありがとうございましたー。

  • >>たけぞ さま

    助けになったみたいで,よかったです
    また,面白いTipsを書ければと思いますです♪

  • 通りすがり2

    とてもシンプルでわかりやすいサンプルありがとうございました。使わせていただきます!

  • >>通りすがり2 さま

    どうぞどうぞ!ガンガンお使いくださいませ!!
    いいモノが出来上がるのを,期待していますです

  • ちょっと立ち寄りました

    🙁
    クライアントからデータを送信しましたぁ~
    サーバー側がうごいてるみたいなので、
    送信はできてるみたいなのですが

    サーバー側で下記のエラーが発生して停止しました。


    listBox1.Items.Add(st + ” , ” + e.FileName);

    有効でないスレッド間の操作:コントロールが
    作成されたスレッド以外のスレッドから
    コントロール’listBox1’がアクセスされました


    そのあとクライアント側で
    m_msg.DataTrance(m_mode, st);
    のところでも上記と同じメッセージが発生して停止しました。

  • >>ちょっと立ち寄りました さま

    あら?
    IPCを使ったプロセス通信,いつの間にか,スレッド化されちゃった??

    最近,IPCでの実装,やってないからなぁ(汗

    一応このエラーは,スレッド内での,Windows Formコントロールへのプロパティやらメソッド操作のエラーです

    こちらのページを確認して,スレッド対応化をやってみてください
    ワーカースレッドからWindowsコントロールのプロパティをいじりたいとき@ぎんゆぅ~さん

    もし,スレッド対応化が,わけわからないときは,ご連絡ください
    こっちの手の空いた時に,サンプルを書き換えてみますです♪

    お願いしますわん♥

  • ちょっと立ち寄りました

    Form1_Load の先頭行で
    Form1.CheckForIllegalCrossThreadCalls = false;

    を呼んでみるとみため正常に動きます。


    もう一つはリストボックスをスレッドセーフにするため

    delegate void ListBoxDelegate(string text);
    internal void AddText(string text) {
    listBox1.Items.Add(text);
    }

    を追加して
    listBox1.Items.Add(st + ” , ” + e.FileName);
    この部分を以下のように変更する
    Invoke(new ListBoxDelegate(AddText), st + ” , ” + e.FileName);

    では、さようなら 😛

  • >>ちょっと立ち寄りました さま

    おっ!
    何とか動いたみたいですね

    よかったよかった!!

    IPCなプロセス間通信
    スレッドセーフ化の対応が必要みたいなので,ご注意くださいませ!>後から来られる方♪

  • 匿名

    素晴らしいです。
    すごく参考に、というか勉強になりました。
    ありがとうございます!

  • >>匿名 さま

    ありがとうございます

    古い技術になりつつありますが,このプロセス間通信,お手軽に使えるんで
    うちでもちょこちょこ利用してますです

    また何かありましたら,よろしくです

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <img localsrc="" alt="">