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() を呼び出すたびに
サーバ側で,デリゲートが呼び出される仕組みです

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

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