読者です 読者をやめる 読者になる 読者になる

ServiceMain

今回はWindowsのシステムサービスを作る・・・。

ServiceMainは、このサービスのメイン処理を担う部分・・・。

ServiceMain 関数

まず、

f:id:BG1:20170318144512p:plain

コンソールアプリケーションで作成・・・。
(Win32プロジェクトでもできるが、コンソールアプリだと疑似サービスを作成して独自に追加した処理をデバッグするような方法ができるので、こちらのほうがいい・・・。)

ServiceMain.cppで、

必要な関数、グローバル変数の宣言・・・。

エントリポイントはServiceMain・・・ではなく、

_tmainである・・・。(または_tWinMainでも可・・・。)
この部分は、[コントロールパネル]の[管理ツール]の[サービス]でServiceMainサービスの開始をした時に実行される・・・。
SERVICE_TABLE_ENTRY型変数steでサービス名とServiceMain関数のアドレスを指定したら、StartServiceCtrlDispatcherで登録・・・。
以降、制御がStartServiceCtrlDispatcherの中に移り、サービスが終了するまで出てこない・・・。
ServiceMainが別スレッドで実行されて、以降はServiceMainの処理に移る・・・。
あと、一応動作確認用のイベントログの準備をしている・・・。

ServiceMainでは、

RegisterServiceCtrlHandlerでさまざまなサービス操作に対するハンドラHandlerを登録する・・・。

SetServiceStatusでサービス状態をSERVICE_START_PENDING(開始中)にセット・・・。
イベントログにも"SERVICE_START_PENDING"・・・。
でそのあとにサービス開始時の独自の処理とかを書くが、今回は何もしない・・・。

独自の処理が終ったら、SetServiceStatusでサービス状態をSERVICE_RUNNING(実行中)にセット・・・。
イベントログにも"SERVICE_RUNNING"・・・。
bRunをTRUEにして、サービスメインループが続くようにする・・・。

今回は、1秒ごとに"ServiceMainLoop!"をイベントログに出力するだけ・・・。

さて、Handlerでは、

SERVICE_CONTROL_STOP(サービスの停止)が要求された時、SetServiceStatusでサービス状態をSERVICE_STOP_PENDING(停止中)にする・・・。
(停止にはしない・・・。あくまでも、これから停止するという状態・・・。)
"SERVICE_STOP_PENDING"のイベントログを出力したら、停止処理・・・といっても、bRunをFALSEにするだけ・・・。
これで、ServiceMainのループから抜ける・・・。
また、

SERVICE_CONTROL_INTERROGATEでは、システムからサービス状態の更新要求が来た時に、SetServiceStatusで更新する・・・。
ただ、今回は1度も来なかった・・・。

ServiceMainループから抜けたら、SetServiceStatusでSERVICE_STOPPEDをセット・・・。これで完全に停止したと言えるので、イベントログで"SERVICE_STOPPED"と出力して終わる・・・。

f:id:BG1:20170318152904p:plain

管理者権限でcmd.exeを実行・・・。
exeのある場所に移動したら、

sc create <サービス名> binPath= <exeのフルパス>

でサービスを登録する・・・。

C:\Project\Cloud\github.com\Sample\winapi\ServiceMain\ServiceMain\src\ServiceMai
n\debug>sc create ServiceMain binPath= "C:\Project\Cloud\github.com\Sample\winap
i\ServiceMain\ServiceMain\src\ServiceMain\debug\ServiceMain.exe"
[SC] CreateService SUCCESS

C:\Project\Cloud\github.com\Sample\winapi\ServiceMain\ServiceMain\src\ServiceMai
n\debug>

こんな感じ・・・。

f:id:BG1:20170318153917p:plain

[コントロールパネル]から[サービス]を選択・・・。

f:id:BG1:20170318154031p:plain

ServiceMainが追加されてる・・・。
開始はしていない・・・。

f:id:BG1:20170318154352p:plain

手動で開始・・・。

f:id:BG1:20170318154514p:plain

[コントロールパネル]から[イベントビューアー]を見ると、

f:id:BG1:20170318154731p:plain

ServiceMainでSERVICE_START_PENDINGが出力されているのが確認できる・・・。

f:id:BG1:20170318155008p:plain

その次にはSERVICE_RUNNINGも出ているし、

f:id:BG1:20170318155158p:plain

以降はServiceMainLoop!が出ている・・・。

f:id:BG1:20170318155506p:plain

停止すると、

f:id:BG1:20170318155557p:plain

こうなり、

f:id:BG1:20170318155658p:plain

SERVICE_STOP_PENDINGが出て、

f:id:BG1:20170318155905p:plain

最終的には、SERVICE_STOPPEDとなる・・・。
(SERVICE_CONTROL_INTERROGATE)はなかった・・・。

ちなみに、サービスの削除は、

C:\Project\Cloud\github.com\Sample\winapi\ServiceMain\ServiceMain\src\ServiceMai
n\debug>sc delete ServiceMain
[SC] DeleteService SUCCESS

で、

f:id:BG1:20170318160244p:plain

確かにServiceMainが消えてる・・・。

Sample/winapi/ServiceMain/ServiceMain/src/ServiceMain at master · bg1bgst333/Sample · GitHub