別プロセスにコマンドライン引数を貯める
前提
目的
以下の場合を想定して作成した。
- コマンドライン引数を用いて、アプリケーションを操作したい
- アプリケーションは多重起動させたくない
- アプリケーションはコマンドラインアプリケーションとして提供。
- でも複数起動されたときの引数は保持したい (今回はココ)
方法
WindowsFormsApplicationBaseやSocketを使って実装する手段もあったが、
今回は簡単にアプリケーション間通信が実装できるWCFを使った。
そのため、引数を投げるクライアントと受け取り、処理するサーバに分けて実装した。
手順
参考にも記載しているが、ほぼ Part 2. Hello World WCF サーバの開発 と Part 3. Hello World WCF クライアントの開発 の丸写しなので読める人はそっちを見たほうがよいと思う。
1. サーバー側
Part 2. Hello World WCF サーバの開発を参考に実装
- 下記のコードをビルドする。
Program.cs
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace Sample.Server
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(WcfService)))
{
host.AddServiceEndpoint(typeof(WcfService), new NetTcpBinding(),
"net.tcp://localhost:28661/Sample.Server/WcfService");
// メタデータ取得用のエンドポイント。
// 手順2のサービス参照の追加で必要。
// 処理を実行するために管理者権限が必要となる。
// サーバー処理としては無くても動く。
host.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
host.Description.Behaviors.Remove(typeof(ServiceMetadataBehavior));
host.Description.Behaviors.Add(new ServiceMetadataBehavior {
HttpGetEnabled = true,
HttpGetUrl = new Uri("http://localhost:8000/Sample.Server/WcfService/mex")
});
host.Open();
Console.WriteLine("WCF サーバを起動しました。");
// 終了待機用の入力待ち
Console.ReadLine();
host.Close();
}
}
}
}
WcfService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace Sample.Server
{
// クライアント側から呼び出せる部分
[ServiceContract]
public class WcfService
{
static List<String[]> args_list = new List<String[]>();
[OperationContract]
public string GetMessage(string[] args)
{
args_list.Add(args);
var result = string.Empty;
foreach(string[] args_for_res in args_list)
{
result = result + "\n" + String.Join(" ", args_for_res);
}
return result;
}
}
}
2. クライアント側
Part 3. Hello World WCF クライアントの開発を参考に実装
- クライアント側のプロジェクトを作成する。
- サーバー側を管理者権限で起動して待機させる。 (メタデータの公開周りで権限が必要?)
- プロジェクトの[参照]を右クリックし [サービス参照の追加] を開く。
- http://localhost:8000/Sample.Server/WcfService/mex を [アドレス] に入れて [OK] する。
- Connected Services > ServiceReference1 が追加される。
- 下記のコードからビルド。
- クライアント側に引数を渡して実行すると、クライアント側でサーバに保存された引数が表示される。
Program.cs
using System;
namespace Sample.Client
{
class Program
{
static void Main(string[] args)
{
ServiceReference1.WcfServiceClient proxy = new ServiceReference1.WcfServiceClient();
string ret = proxy.GetMessage(args);
proxy.Close();
Console.WriteLine(ret);
}
}
}
参考
Part 1. WCF に導入されている新たな設計概念 – とあるコンサルタントのつぶやき
Part 2. Hello World WCF サーバの開発 – とあるコンサルタントのつぶやき
Part 3. Hello World WCF クライアントの開発 – とあるコンサルタントのつぶやき
備考
C#|二重起動を禁止してコマンドライン引数を取得する | 貧脚レーサーのサボり日記
WindowsFormsApplicationBase を用いて実現する方法。
今回はコマンドラインアプリケーションだったため使わなかったが、
UI付きであればこちらのが楽だろう。