関連記事
- 【#CSHARP】ソリューション内でサービス,Winformアプリを混在で作成させ,バイナリ出力先を同じにするとサービスが起動しない 【2024年02月08日(木)】
- 【#PHP】謎な #Laravel 案件 引き渡したじ 【2024年01月11日(木)】
- 【C#】謎な改造アプリ,SIMD命令を導入して高速化しようか,思案中 【2023年11月14日(火)】
- Javaの”やらかし”でC#と人気逆転か 激変プログラミング言語人気ランキング 【2023年10月18日(水)】
- 【#CSHARP】次の案件のスケルトン書いてgitサーバに登録するなどと 【2023年05月16日(火)】
【追記】
WCF(Windows Communication Foundation)にて
プロセス間通信するサンプルを書いてみました(Windowsサービス~Winフォーム間 ローカルPCリモートPC対応)
参考にどぞー
C#での自PC内プロセス間通信(WCF版:Windowsサービスにて実装)@ぎんゆぅ~さん
またまた,必要に迫られて実装をば...
最初,Localhostに対して,ソケットで通信しようかと思いましたが…
Net Frameworkに,便利なクラスが追加されているそうで
- IpcServerChannelクラス
IpcClientChannelクラス
なお,こちらのページを参考にしました
あわせて,御確認ください
[C#][Program]C# .NETリモーティングを使ったプロセス間通信@tetsuarossa
[C#][Program]C# .NETリモーティングを使ったプロセス間通信 その2@tetsuarossa
tetsuarossaさま,サンクスです 🙂
【追記:09/04/15】
ここに記載したコード,サンプルプロジェクトとして,丸ごとアップしておきます
ダウンロードは,こちら@C#
ご自由にお使いくださいませ!
なお,バグってたら,すまんでごわす
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() を呼び出すたびに
サーバ側で,デリゲートが呼び出される仕組みです
情報共有クラスにプロパティを追加すれば
サーバ側で,設定した値をクライアントでも,読み出せるはず,です(汗
また,私自身がどこかで使うかもしれないので
ここに記載しておきますです…
ありがとうございました。とても参考になりました。 😉
なかなか form 形式での sample が見つからなかったので。
蛇足かもしれませんが 2 の所の using System.Runtime.Remoting の部分で、ソリューションエクスプローラで各 exe の参照設定に System.Runtime.Remotingを追加しないと私の場合ビルドエラーになってしまいました。
重ねてありがとうございます。参考になりました。
>>通りすがり さま
ようこそ!
参考になったみたいで,よかったです
参照設定の件,(1)にちょろっと,書いてありますです
見落とされたかな?? 😉
また,面白そうなコードが出てきたら,ここに記載していきますです 🙂
Tag値のとり方がわからず、ここへたどり着きました。ありがとうございましたー。
>>たけぞ さま
助けになったみたいで,よかったです
また,面白いTipsを書ければと思いますです♪
とてもシンプルでわかりやすいサンプルありがとうございました。使わせていただきます!
>>通りすがり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なプロセス間通信
スレッドセーフ化の対応が必要みたいなので,ご注意くださいませ!>後から来られる方♪
素晴らしいです。
すごく参考に、というか勉強になりました。
ありがとうございます!
>>匿名 さま
ありがとうございます
古い技術になりつつありますが,このプロセス間通信,お手軽に使えるんで
うちでもちょこちょこ利用してますです
また何かありましたら,よろしくです