C# WPF IPC 二重起動時にコマンドライン引数を渡す
2017年8月
あるアプリを重複して起動したとき、後から起動した方は先に起動していた方へデータを渡して終了したい、ということはよくある。
「C# SendMessageで文字列を送受信する方法」
ではFormアプリでWin32APIのSendMessageを使って文字列を送信する方法を紹介した。
今回はWPFアプリでプロセス間通信を利用して実装した。
目的の動作
- あるアプリA(実行ファイル名「MyApp.exe」)が起動しているとする。
- エクスプローラー上でMyApp.exe(またはそのショートカットアイコン)へ適当なファイルをD&Dする。
- もう一つのアプリAが起動開始する(アプリA'とする)。
このとき、D&DされたファイルのフルパスがアプリA'のコマンドライン引数となっている。
- アプリA'は画面に表示される前にアプリAへコマンドライン引数を渡す。アプリA'はここで終了する。
- アプリAはアプリA'からコマンドライン引数を受け取り、処理を開始する。
プログラムの流れ
プロセス間通信(IPC:InterProcess Communication)は同一PC内にサーバー/クライアントを作成し、
リモートオブジェクトを介してデータをやりとりする。プロセスとは起動しているアプリそれぞれを指す。
プログラムの流れは次の通り。
- 先に起動したアプリはサーバーとなり、IPCのフレームワークにチャンネル(アクセス経路)を登録する。
- サーバーはリモートオブジェクトを作成し、IPCネットワーク上に公開する。
- 後から起動したアプリはクライアントとなり、リモートオブジェクトにアクセスする。
- クライアントはサーバーに渡したいデータをリモートオブジェクトにセットし、サーバーに通知する。
ここで、クライアント側アプリは自身を終了する(二重起動禁止を想定している)。
- 通知を受け取ったサーバーはリモートオブジェクトからデータを取り出し、処理する。
【参考】
.NET アプリケーションのパフォーマンスとスケーラビリティの向上 - 第 11 章 「リモート処理パフォーマンスの向上」
…の、「図 11.1.NET リモート処理のアーキテクチャ」
Visual C# を使用して参照渡しのオブジェクトをリモート サーバーにマーシャリングする方法
Microsoft Visual C# を使用してリモート サーバーを作成する方法
Visual C# を使用してリモート サーバーにアクセスするクライアントを作成する方法
方法 : イベントを発生させる/処理する
プログラムの内容
【ダウンロード】
前項「プログラムの流れ」に沿った素直なソース/プロジェクトは → 「IpcArgsTest1.zip」
MainWindowクラスに記述する量を少なくし、使いやすくしたのが → 「IpcArgsTest2.zip」
動作確認環境は .NET Framework 4.6.1 / VisualStudioCommunity 2017
以下、「IpcArgsTest2.zip」に含まれるソースを示す。
MainWindow.xaml.cs
【動作内容】
- Window_Initialized()内でIpcManagerクラスのインスタンスを生成する。
- コールバック関数(例:IpcCallback_ClientStarted())を指定してIPC接続を確立する。
→クライアントだった場合はアプリを終了する。
- サーバーだった場合、2個目のアプリの起動時にコールバック関数が呼ばれる。
→コマンドライン引数を受け取って任意の処理へ。
サーバーチャンネル名はIPCを使う他アプリのチャンネル名と一致しないようにする必要がある。GUIDを与えればよい。
GUID生成ツール→"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\guidgen.exe"
IpcUtility.cs (class IpcManager, class IpcRemoteObject)
【ポイント】
- 今回の目的ではフォーマッタの指定やシリアライズ属性の付与は不要。
- リモートオブジェクトの生成がSingletonかSingleCallか意識する必要なし(クライアントは直ちに終了するので)。
- クライアントからのコールバックはMainWindowとは別のスレッドで発生する。
処理をMainWindow(のスレッド)へ戻すには、MainWindow.Dispatcher.Invoke(callback)。
コンソールアプリで説明しているサンプルでは別スレッドで動作していることが分からず、WPFに応用するときにつまずく。
◆ ◆ ◆
アプリに組み込むなら追加すべき記述量が少なく、直感的に分かりやすいことが望ましい。
MainWindowに数行付け足すだけで目的達成できれば理想的。
(C) 『昼夜逆転』工作室