次の方法で共有


Service ServiceMain 関数

サービス 制御プログラムが新しいサービスの実行を要求すると、サービス コントロール マネージャー (SCM) によってサービスが開始され、制御ディスパッチャーに開始要求が送信されます。 コントロール ディスパッチャーは、サービスの ServiceMain 関数を実行する新しいスレッドを作成します。 例については、「ServiceMain 関数 の作成」を参照してください。

ServiceMain 関数は、次のタスクを実行する必要があります。

  1. すべてのグローバル変数を初期化します。

  2. RegisterServiceCtrlHandler 関数を直ちに呼び出して、サービスの制御要求を処理する ハンドラー 関数を登録します。 RegisterServiceCtrlHandler の戻り値は、サービスの状態を SCM に通知する呼び出しで使用される サービス状態ハンドル です。

  3. 初期化を実行します。 初期化コードの実行時間が非常に短い (1 秒未満) と予想される場合は、ServiceMainで初期化を直接実行できます。

    初期化時間が 1 秒を超えると予想される場合、サービスは次のいずれかの初期化手法を使用する必要があります。

    • SetServiceStatus 関数を呼び出してSERVICE_RUNNINGを報告しますが、初期化が完了するまでコントロールは受け入れなくなります。 この処理を行うには、dwCurrentStateを SERVICE_RUNNING に設定して SetServiceStatus を呼び出し、SERVICE_STATUS 構造体で dwControlsAccepted を 0 に設定 します。 これにより、SCM は準備が整う前にサービスに制御要求を送信せず、SCM を解放して他のサービスを管理できるようになります。 この初期化方法は、特に自動開始サービスのパフォーマンスに推奨されます。

    • SERVICE_START_PENDINGを報告し、コントロールを受け入れず、待機ヒントを指定します。 サービスの初期化コードで、最初の待機ヒント値よりも長い時間がかかると予想されるタスクを実行する場合、コードでは、SetServiceStatus 関数を定期的に呼び出して (場合によっては、修正された待機ヒントを使用して) 進行状況が行われていることを示す必要があります。 初期化が進行している場合にのみ、SetServiceStatus を呼び出してください。 それ以外の場合、SCM は、サービスが進行中であると仮定してサービスがSERVICE_RUNNING状態になるまで待機し、他のサービスの開始をブロックできます。 初期化 実行しているスレッドが本当に進行していることを確認できる場合を除き、SetServiceStatus を別のスレッドから呼び出さないでください。

      この方法を使用するサービスでは、長い初期化中に、チェック ポイント値を指定し、値を定期的にインクリメントすることもできます。 サービスを開始したプログラムは、QueryServiceStatus呼び出すか、QueryServiceStatusExして SCM から最新のチェック ポイント値を取得し、その値を使用して増分進行状況をユーザーに報告できます。

  4. 初期化が完了したら、SetServiceStatus呼び出してサービスの状態をSERVICE_RUNNINGに設定し、サービスが受け入れるように準備するコントロールを指定します。 コントロールの一覧については、SERVICE_STATUS 構造体を参照してください。

  5. サービス タスクを実行するか、保留中のタスクがない場合は、呼び出し元に制御を返します。 サービスの状態が変更された場合、新しい状態情報を報告するために SetServiceStatus呼び出す必要があります。

  6. サービスの初期化中または実行中にエラーが発生した場合、サービスは SetServiceStatus呼び出して、クリーンアップが長くなる場合にサービスの状態をSERVICE_STOP_PENDINGに設定する必要があります。 クリーンアップが完了したら、SetServiceStatus 呼び出して、終了する最後のスレッドからサービスの状態をSERVICE_STOPPEDに設定します。 エラーを識別するには、dwServiceSpecificExitCode を設定し、dwWin32ExitCode SERVICE_STATUS 構造体のメンバーを してください。

ServiceMain 関数 を記述する