C#ではアプリ間でデータの受け渡しがができるプロセス間通信という仕組みがあります。
プロセス間通信は以下のようなクラスを使って実現する事が出来ます。
System.Runtime.Remoting.Channels.Ipc.IpcServerChannel クラス
System.Runtime.Remoting.Channels.Ipc.IpcClientChannel クラス
System.Runtime.Remoting.Channels.ChannelServices クラス
System.Runtime.Remoting.RemotingServices クラス
System.MarshalByRefObject クラス
System.Runtime.Remotingの参照を追加
必要なクラスを使えるようにするためフレームワークの参照の追加を行います。
メニューから「プロジェクト(P)」→「参照の追加(R)...」で参照マネージャーを開き、
「System.Runtime.Remoting」を追加しましょう。
共有するデータ構造を作成
public class IpcTestObject : MarshalByRefObject { public string TestField; public void SetTextField(string text) { TestField = text; } }
このクラスはサーバー側とクライアント側の両方で利用します。
サーバーとクライアントがそれぞれこのクラスのフィールドやメソッドにアクセスする事でデータを共有する事ができます。
サーバー側
サーバー側は、サーバーチャネルの作成→チャネルを登録→共有するオブジェクトを公開という流れになります。
public partial class MainWindow : Window { private IpcServerChannel Channel; private IpcTestObject TestObj; public MainWindow() { InitializeComponent(); TestObj = new IpcTestObject(); TestObj.TestField = "TEST!"; // "IpcTest"という名前でIPCチャネルを作成 Channel = new IpcServerChannel("IpcTest"); // 作成したチャネルを登録 ChannelServices.RegisterChannel(Channel, true); // "TestObj"という名前でオブジェクトを公開 RemotingServices.Marshal(TestObj, "TestObj", typeof(IpcTestObject)); } }
クライアント側
クライアント側は、クライアントチャネルの作成→チャネルを登録→共有されたオブジェクトを取得という流れになります。
public partial class MainWindow : Window { private IpcClientChannel Channel; private IpcTestObject TestObj; public MainWindow() { InitializeComponent(); // IPCチャネルを作成 Channel = new IpcClientChannel(); // 作成したチャネルを登録 ChannelServices.RegisterChannel(Channel, true); // サーバーが公開した名前を使ってオブジェクトを取得 var url = "ipc://IpcTest/TestObj"; TestObj = (IpcTestObject)Activator.GetObject(typeof(IpcTestObject), url); } }
しばらくアクセスしないと接続が切れる
プロセス間通信はしばらく通信が行われないと接続が切断されて以下のような例外が発生します。
System.Runtime.Remoting.RemotingException はハンドルされませんでした。
オブジェクト '/TestObj' が切断されたか、サーバーに存在しません。
このような時は、以下のように共有するオブジェクトのInitializeLifetimeService()メソッドをオーバライドして null を返すようにする事で回避できます。
public class IpcTestObject : MarshalByRefObject { public string TestField; public void SetTextField(string text) { TestField = text; } public override object InitializeLifetimeService() { return null; } }
コメントをお書きください
kaichan (月曜日, 01 3月 2021 22:17)
残念だけど.net 5では未対応。WCFもだけど。
クロスプラットフォームはありがたいんだけど、過去のプログラム
動かないの時々ある。今日見つけたのはACL取得してたクラスが廃止とか。