Windows サービスを柔軟に管理するサービスマネージャの製作:パート1はじめにこの記事は2部構成の前半です。パート1では、.NET Frameworkにおける「サービス」の起動方法や使い方、プラグアンドプレイサービスの追加方法などについて詳しく説明しますパート2はサービスの仕組みの詳細です。.NET Remotingやリフレクションを使用したアプリケーションドメインのローディングとアンローディングなど、高度なトピックを取り上げます。 こんなことを考えたのは私が最初ではなく、また最後でもないでしょう。事実、リソースセクションには同様の目的で書かれた記事が2つあり、私もそれを参考にしました。しかし、使いやすさと柔軟性では、僭越ながら私の実装がそれらに勝ると思います。 まず、用語について一言触れておきましょう。私たちはよくWindowsサービスとか、Webサービス、サービス指向アーキテクチャなどと言いますが、ここで使われる「サービス(service)」という単語は、これらの概念の本当の意味を表すのに必ずしも適切な単語ではありません。英語には代わりに使用できる単語があまりないのですが、ITの世界で手垢にまみれていない代替語を探すと、奉仕とか世話を意味する「ミニストレーション(ministration)」あたりが最適でしょうか。私自身は、難しげに聞こえる言葉を使いたがる性格ですが、ここは従来の業界用語を踏襲し、特に概念を明確化する必要があるときは、適切な修飾語の助けを借りることにします。 ここで紹介しようとしている新概念は、今回取り上げるWindowsサービスの名前「.NET Service Manager」と関係があります。このWindowsサービスは、平たく言えば、本来なら独立したWindowsサービスとしてインストールすべきサービスを、ドラッグアンドドロップやXCOPYでインストールするサービスです。基本的には、ユーザーがログインしていない間も実行しておきたい長時間稼動のプロセスや、時間限定のプロセスなどが、Windowsサービスの候補となります。 残念ながら、.NETでもWindowsサービスの実装は簡単ではありません。Windowsサービスのインストールや開始/停止は[サービス]MMCスナップインで手動で行わなければなりません。これは非常に面倒な作業であり、Windowsサービスがいくつもあると、サービスリストが手に負えなくなります。 そこで、今回の.NET Service Managerの出番となります。このアプリケーションでは、Windowsサービスを書き、インストールし、(MMCスナップインを使って)開始する、という作業が一度だけで済みます。その後は、ASP.NETなどと同等(またはそれ以上)のXCOPYを使用して実際の処理を行えるようになります。アセンブリ属性を適用し、簡単なインターフェイスを実装するだけで、どのような.NETコードライブラリ(DLL)アセンブリでも.NET Service Managerの下で実行できます。このようなアセンブリを、私は「被管理サービス」と呼んでいます。「Windowsサービスのように動作するものの、実は.NET Service Managerの管理下にあるサービス」の意味です。 この記事(パート1、パート2とも)で「サービス」に言及するときは、修飾語を付け、Windowsサービス(従来の「NTサービス」)なのか、被管理サービス(上記パラグラフで説明したサービス)なのかを示すことにします。パート1では、被管理サービスの実装方法について詳しく説明します。この説明に従えば、.NET Service Managerの働きの仕組みを知らなくても、.NET Service Managerとその機能を利用することができます。働きの仕組みについては、パート2で説明します。 .NET Service Managerを使えば、サービスをプロセスディレクトリにコピーするだけでインストールと開始ができます。また、サービスの更新も同じ配備メカニズムで簡単に行うことができ、その際に.NET Service Manager自体を停止・開始する必要はありません。すべての被管理サービスは独自のアプリケーションドメインで動作しているので、あるサービスを更新しても、他のサービスには何の影響もありませんし、.NET Service Manager自体を停止させる必要もありません。同様に、ある被管理サービスを停止させたいときは、そのDLLをプロセスディレクトリから取り除く(削除もしくは移動する)だけで済み、インストール同様、アンインストールも簡単にできます。 .NETがコードライブラリのconfigファイルをサポートしていないことはご存じでしょう。それにはちゃんとした理由がありますが、私自身は「その機能があればすごく便利なのに」と思うケースを何度も経験しています。被管理サービスもそうしたケースの1つです。そこで、設定値を「app.config」のようなファイル(たとえば、「SampleService.dll.config」)に格納するための簡単なインターフェイスを作ってみました。このconfigファイルは、アプリケーション設定値を持つ典型的なconfigファイルと同じ規則に従っています。この技術の実装例も後で紹介します。 あるコードを被管理サービスとして動作させるために必要な手順は、次の2つだけです。
これを使用して、サービスの表示名と、サービスエントリポイントとなる型(ステップ1でインターフェイスを実装した型)を指定します。 もう1つ、configファイルの機能を利用するためのステップ3を加えることもできますが、これが必要なのは、その被管理サービスが変更可能な設定値を必要としている場合だけです。この3つのステップのそれぞれについて、以下で説明していきます。 もちろん、「ServiceBroker.dll」アセンブリへの参照も必要ですが、これは.NET Service Managerとともにインストールされるので、インストール先ディレクトリ(たとえば、「C:Program FilesLittlechip.NET Service Manager」)で参照すればよいでしょう。あるいは、記事「Where’s My Assembly?」のように共通のアセンブリ参照ディレクトリにコピーして、そこで参照することもできます。 ServiceBroker.IServiceを実装する ServiceBrokerは.NET Service Managerに付随するアセンブリで、.NET Service Managerのエンジンとして働くと同時に、.NET Service Managerと被管理サービスとの対話に必要な型を提供します。 リスト1 「IService.cs」
using System; namespace ServiceBroker { ///<summary> /// Interface that all services using the /// ServiceBroker must implement on the type specified /// by the <see cref= /// "ServiceEntryPointAttribute.EntryPointTypeName"/>. ///</summary> public interface IService { ///<summary> /// Starts the service functionality. ///</summary> void StartService(); ///<summary> /// Stops the service functionality. ///</summary> void StopService(); } } ご覧のとおり、被管理サービスのインターフェイスは実に簡単で、開始メソッドと停止メソッドが必要とされるだけです。これは、もちろん、[サービス]MMCスナップインで使用できる典型的な操作に対応しています。Windowsサービスの再開という操作では、 例として、きわめて単純な被管理サービスを実装してみました。これは実装方法を示すためだけの実装であり、名前はSampleServiceです。このアセンブリ中で リスト2 「Test.cs」
using System; namespace SampleService { ///<summary> /// Summary description for Test. ///</summary> public class Test : ServiceBroker.IService { #region IService Members public void StartService() { ServiceBroker.Logger.WriteToLog(AppSettings["StartText"], System.Diagnostics.EventLogEntryType.Information); } public void StopService() { ServiceBroker.Logger.WriteToLog(AppSettings["StopText"], System.Diagnostics.EventLogEntryType.Information); } #endregion } } もちろん、サービスを実装するのであれば、 属性を適用する もちろん、属性を適用せず、リフレクションで済ませる方法もあります。アセンブリ中の型を調べ、 アセンブリに対するカスタム属性の適用はきわめて簡単です。Visual Studioを使っている場合、コードライブラリプロジェクトでは既定で「Assembly.cs」(VBなら「Assembly.vb」)ファイルが生成されます。そこで、アセンブリレベル属性を指定することが求められます。実際にアセンブリレベル属性を指定する場所はどのコードファイルでもかまいませんが、 リスト3 「Assembly.cs」
[assembly: ServiceBroker.ServiceEntryPoint("SampleService", 生成される「Assembly.cs」ファイルには、普通、大量のコメントと少量の標準アセンブリレベル属性(タイトル、内容記述、会社、著作権など)が含まれています。私は、 また、既にお気づきのことと思いますが、私はServiceBrokerアセンブリからのカスタム属性を適用しています。この属性のコンストラクタは引数を2つとります。1つは被管理サービスの表示名、もう1つは、サービスの開始・停止の際に.NET Service Managerに使用させる型の完全型名です。2つ目の引数に指定する型が、 変更可能なアプリケーション設定値が特に必要ない場合は、ここで作業は終わりです。これをコンパイルして、.NET Service Managerのプロセスディレクトリ(つまり、.exeが置かれているディレクトリ)にドロップします。後は.NET Service Managerを実行すれば、それがアセンブリを自動的にロードし、サービスエントリポイント型を見つけてインスタンスを作成し、その型の 被管理サービスを更新するときは、必要な変更を施し、コンパイルした新バージョンを同じディレクトリにドロップします。.NET Service Managerは、稼動中に新バージョンを検出すると、旧バージョンを停止してアンロードし、新バージョンをロードして開始します。同様に、DLLファイルをディレクトリから移動または削除しても、.NET Service Managerにそれを停止してアンロードさせることができます。 DLLのconfigファイルを使用して柔軟性を強化する ServiceBrokerの いずれにせよ、configファイルのフォーマットは標準の「app.config」ファイルと同じです。ただし、ServiceBrokerのconfigハンドラが認識するのはアプリケーション設定値だけです。SampleServiceアセンブリで使用するconfigファイルをリスト4に示します。 リスト4 「SampleService.dll.config」
<?xmlversion="1.0"encoding="utf-8"?> <configuration> <appSettings> <add key="StartText" value="This is where you would implement logic configファイルを使用するには、 リスト5 完全な「Test.cs」
using System; namespace SampleService { ///<summary> /// Summary description for Test. ///</summary> public class Test : ServiceBroker.IService { internal static ServiceBroker.Config AppSettings = new ServiceBroker.Config(); #region IService Members public void StartService() { ServiceBroker.Logger.WriteToLog(AppSettings["StartText"], System.Diagnostics.EventLogEntryType.Information); } public void StopService() { ServiceBroker.Logger.WriteToLog(AppSettings["StopText"], System.Diagnostics.EventLogEntryType.Information); } #endregion } } 結局、追加するのは、 さあ、終わりました。これで、XCOPYで配備でき、ホット更新が可能で、簡単に設定できるWindowsサービスが得られました。他の「app.config」ファイルとは違い、ServiceBrokerはユニークです。configファイルを監視して変更の有無を察知し、configファイルが更新されたときは、キャッシュに記憶されている設定値(アプリケーションの実行中、高速アクセスのためにメモリにロードされています)を更新できます。しかも被管理サービスを再開する必要はありません。 .NET Service Managerのインストーラは、.NET Service ManagerをLocal Systemアカウントの下で実行されるものとしてインストールします。しかし、事情が許せば、これをもっと権限の小さなアカウントに変更することをお勧めします。実は、すべての被管理サービスが同じWindowsサービスのパーミッションの下で実行されることが、.NET Service Managerの弱点でもあります。もっときめ細かな管理が必要なときは、さらに別のWindowsサービスを開発しなければなりません。 ダウンロードサンプルに含まれているインストーラを実行し、.NET Service Manager Windowsサービスを開始してください。これでいつでも被管理サービスの作成と配備ができます。パート2では、なぜ.NET Service Managerの下でこれが可能になるのかを説明します。 参考資料
著者紹介J. Ambrose Little(J. Ambrose Little)
ASPAlliance編集長。ASPInsiderであり、Microsoft ASP.NET MVPでもある。現在はWebアーキテクトとして、フロリダ州タンパにある大手信用組合に勤務。これまでに、Verizon社のコンサルタントとしてXML Webサービスと中間層コンポーネントを開発し、BOk Financial社のWebサービス部門で同社イントラネット用にASP.NETアプリケーションを開発。.NET以前にも数年のプログラミング経験があり、ASPとVB COM/DCOMを用いたWebアプリケーション開発に従事。
中世ヨーロッパ史の研究が趣味で、この分野で学士号を取得。ソフトウェア開発以外では、映画鑑賞、読書、執筆、弁証論、ビリヤード、フーズボール、チェス、バドミントンなどを楽しむが、最大の楽しみは、もちろん、妻Christianeに娘Bridgetと過ごすことである。 メールの宛先はambrose@aspalliance.com。 関連記事 最新トップニュース
|
|