サービスのプロパティに「回復」というタブがありまして,エラー発生時の処理を選ぶことができるのですが,自作のサービスでこいつを使うのにちょっと難儀しました。
まず経験的にわかっているのは,プログラムが未処理例外で落ちたときにはこの回復オプションを使ってサービスを再起動させられるということ。しかしそれを狙ってやるのはプログラムとしてどうよという気がしますし,ひとつのexeに複数のサービスが入っていた場合,すべてのサービスを巻き添えにしてしまうことになります。なのでなんとか「エラーとして」サービスを終了させられないかと考えていろいろ試してみました。
そもそもサービスのエラーとはなにかというと,A service is considered failed when it terminates without reporting a status of SERVICE_STOPPED to the service controller.(SERVICE_FAILURE_ACTIONS Structure (Windows):)なのだそうです。なんだそれだけかと思ってSetServiceStatus()を呼ばずにServiceMainから抜けてみたのですがダメ。プロセスが死んでくれません。がんばってぐぐっているうちに Geoff Chappell さんのサイトで Note also that the setting is live. SVCHOST keeps a reference count for each service. This count is incremented before calling ServiceMain and when registering a stop callback. It is decremented when ServiceMain returns and after the stop callback has executed. という記述を見つけたときはコレだ! と思ったのですがよく読んでみたらDLLサービスをSVCHOSTから起動するときの話でした。ダメもとで,ServiceMainから抜ける前にControlService()で自分に停止信号を送ってそれを無視するというのをやってみましたが,やはりプロセスは終了せず。しょうがないのであきらめてExitProcess()することに。うーん。
ちなみに「Windows Vista ではこの動作が変更されており、サービスの状態が SERVICE_STOPPED に設定されていても、サービスの終了コード (SERVICE_STATUS::dwWin32ExitCode メンバによって提供されます) が ERROR_SUCCESS 以外に設定されている場合は、サービスによって失敗時のアクションが要求されます。」(Windows と C++: Windows サービスの機能強化:)なのだそうです。正しい。きわめて正しい。
※コメント投稿者のブログIDはブログ作成者のみに通知されます