Service ServiceMain 関数
サービス 制御プログラムが新しいサービスの実行を要求すると、サービス コントロール マネージャー (SCM) によってサービスが開始され、コントロール ディスパッチャーに開始要求が送信されます。 コントロール ディスパッチャーは、 サービスの ServiceMain 関数を実行する新しいスレッドを作成します。 例については、「 ServiceMain 関数の記述」を参照してください。
ServiceMain 関数は、次のタスクを実行する必要があります。
すべてのグローバル変数を初期化します。
RegisterServiceCtrlHandler 関数を直ちに呼び出して、サービスの制御要求を処理する Handler 関数を登録します。 RegisterServiceCtrlHandler の戻り値は、サービス状態を SCM に通知するために呼び出しで使用されるサービス状態ハンドルです。
初期化を実行します。 初期化コードの実行時間が非常に短い (1 秒未満) と予想される場合は、 初期化を ServiceMain で直接実行できます。
初期化時間が 1 秒を超えると予想される場合、サービスでは次のいずれかの初期化手法を使用する必要があります。
SetServiceStatus 関数を呼び出してSERVICE_RUNNINGを報告しますが、初期化が完了するまでコントロールを受け入れなくなります。 この処理は、SERVICE_STATUS構造体でdwCurrentState が SERVICE_RUNNING に設定され、dwControlsAccepted が 0 に設定された SetServiceStatus を呼び出すことによって行われます。 これにより、SCM は準備が整う前にサービスに制御要求を送信せず、他のサービスを管理するために SCM を解放します。 この初期化方法は、特に自動開始サービスの場合、パフォーマンスに推奨されます。
レポートSERVICE_START_PENDINGし、コントロールを受け入れず、待機ヒントを指定します。 サービスの初期化コードで、最初の待機ヒント値よりも長い時間がかかると予想されるタスクを実行する場合、コードは SetServiceStatus 関数を定期的に呼び出して (場合によっては、変更された待機ヒントを使用して) 進行状況が行われているかどうかを示す必要があります。 初期化が進行している場合にのみ 、SetServiceStatus を呼び出してください。 それ以外の場合、SCM は、サービスが進行中であると仮定してサービスがSERVICE_RUNNING状態になるまで待機し、他のサービスの開始をブロックできます。 初期化を実行しているスレッドが実際に進行していることを確認できる場合を除き、別のスレッドから SetServiceStatus を呼び出さないでください。
この方法を使用するサービスでは、チェックポイント値を指定し、長い初期化中に値を定期的にインクリメントすることもできます。 サービスを開始したプログラムは、QueryServiceStatus または QueryServiceStatusEx を呼び出して、SCM から最新のチェックポイント値を取得し、その値を使用して増分進行状況をユーザーに報告できます。
初期化が完了したら、 SetServiceStatus を呼び出してサービスの状態をSERVICE_RUNNINGに設定し、サービスが受け入れる準備ができているコントロールを指定します。 コントロールの一覧については、 SERVICE_STATUS 構造に関するページを参照してください。
サービス タスクを実行するか、保留中のタスクがない場合は、呼び出し元に制御を返します。 サービス状態を変更すると、新しい状態情報を報告するために SetServiceStatus を呼び出す必要があります。
サービスの初期化中または実行中にエラーが発生した場合、サービスは SetServiceStatus を呼び出して、クリーンアップに時間が長い場合にサービスの状態をSERVICE_STOP_PENDINGに設定する必要があります。 クリーンアップが完了したら、 SetServiceStatus を呼び出して、終了する最後のスレッドからサービス状態をSERVICE_STOPPEDに設定します。 エラーを特定するには、必ずSERVICE_STATUS構造体の dwServiceSpecificExitCode メンバーと dwWin32ExitCode メンバーを設定してください。
関連トピック