Win32: サービスを作成する方法

Windows NT/2000/XP には「サービス」というのがあるが、あれを自分で作る場合、どうすればいいのか。方法は 4 種類。うち 1 種類が C ベースで、2 種類が C++ ベース、最後の 1 種類は .NET Framework を利用したもの。

C ベースの実装方法

これについては、以下のサイトが詳しい。残り 2 つの C++ ベースの方法というのはこれをラップしたものなので、どの方法で実装するにしろ、一度読むことをオススメしたい。

depressionist - 20020821We
http://hp.vector.co.jp/authors/VA015815/200234.html#D20020821

C++ ベースの実装方法 (1)

VC6 の ATL COM AppWizard で作る場合、基本はここから。

  1. [ファイル]→[新規作成]
  2. [プロジェクト]タブで、[プロジェクト名] を入力し、[ATL COM AppWizard] を選択
  3. [ATL COM AppWizard - ステップ 1/1] が開いたら、[サーバー タイプ] で [サービス (EXE)]を選択

これで空のサービスができあがる。出来上がったソースには、サービスを表す CServiceModule というクラスが定義されている。このクラスについては、MSDN に解説がちょっとだけある
グローバル関数 _tWinMain を見ると、起動引数として以下の 3 つが定義されている。

UnregServer
登録を解除する
RegServer
ローカルサーバとして登録する
Service
サービスとして登録する

ここで言う「ローカルサーバ」というのは、マシンローカルで動作する COM サーバのことだ。今回はサービスとして登録したいので、[プロジェクト]→[設定] でダイアログを開いて、[カスタムビルド] タブの [コマンド] を修正する。1 行目に

"$(TargetPath)" /RegServer 

とあるのを、以下に直す (ちなみに、間違えて "/Server" と入力したら、プロセスが終わらなくなった)。

"$(TargetPath)" /Service 

[OK] を押してダイアログを閉じたら、ビルドしてみると、サービスとして登録される。「管理ツール」の「サービス」を起動すると、一覧に追加されているはずだ (デフォルトではプロジェクト名がそのままサービス名として使われる)。何もしないサービスではあるが、起動・停止・再起動はできるし、プロパティの設定も行える。
後は、生成された CServiceModule をいじって、サービスの処理を実装していけばいい。基本的には、メンバ関数 Handler() でサービス操作に対応したり、Run() 内のメッセージループを修正していったりすればいいだろう。以下のサイトが参考になる。

EZ-NET 研究 - ATL でサービスプログラムを作ってみる
http://program.station.ez-net.jp/special/vc/atl/service_vc6.asp

C++ ベースの実装方法 (2)

前項は VC6 での実装方法だが、VC7 では変更が加えられているらしく、CServiceModule のかわりに、CAtlServiceModuleT テンプレートクラスを使用して実装するようになっている。手元に環境がないので、URL の紹介のみ。

MSDN - ATL ライブラリ リファレンス - CAtlServiceModuleT クラス
http://www.microsoft.com/japan/msdn/library/ja/vclib/html/vclrfcatlservicemodulet.asp
EZ-NET 研究 - 【成功版】 ATL でサービスプログラムを作ってみる
http://program.station.ez-net.jp/special/vc/atl/service_vc2003.asp

.NET Framework を使った実装方法

C#VB.NET 等でサービスを実装する場合には、System.ServiceProcess 名前空間にある ServiceBase を継承したクラスを実装することになる。.NET Framework SDK のドキュメントを見ると、「アプリケーションの構築」の中に「Windows サービス アプリケーションの概要」がある。VS.NET は手元になくてわからないのだが、SharpDevelop にもテンプレートがあるので、そっからいじっていけばいい。