SERVICE_MAIN_FUNCTIONA
コールバックシグネチャ
void SERVICE_MAIN_FUNCTIONA(
DWORD dwNumServicesArgs,
CHAR** lpServiceArgVectors
);パラメーター
| フィールド | 型 | 説明 |
|---|---|---|
| dwNumServicesArgs | DWORD | lpServiceArgVectors 配列に含まれる引数の数です。 |
| lpServiceArgVectors | CHAR** | サービスを開始した StartService 関数の呼び出しによって、サービスに渡された null 終端の引数文字列です。引数が無い場合、このパラメーターは NULL になることがあります。それ以外の場合、最初の引数 (lpServiceArgVectors[0]) はサービス名であり、その後に追加の引数 (lpServiceArgVectors[1] から lpServiceArgVectors[dwNumServicesArgs-1] まで) が続きます。 ユーザーがコントロール パネルの [サービス] スナップインを使用して手動サービスを開始した場合、lpServiceArgVectors パラメーターの文字列は、そのサービスのプロパティ ダイアログ ボックスから取得されます ([サービス] スナップインでサービスの項目を右クリックし、[プロパティ] をクリックして、[開始パラメーター] にパラメーターを入力します)。 |
公式ドキュメント
サービスのエントリ ポイントです。
LPSERVICE_MAIN_FUNCTION 型は、このコールバック関数へのポインターを定義します。 ServiceMain は、アプリケーション定義の関数名のプレースホルダーです。
解説(Remarks)
サービス プログラムは、1 つ以上のサービスを開始できます。サービス プロセスは、開始できるサービスごとに SERVICE_TABLE_ENTRY 構造体を持ちます。この構造体には、サービス名と、そのサービスの ServiceMain 関数へのポインターを指定します。
サービス コントロール マネージャーは、サービスの開始要求を受け取ると、(まだ実行されていない場合は) サービス プロセスを開始します。サービス プロセスのメイン スレッドは、 SERVICE_TABLE_ENTRY 構造体の配列へのポインターを指定して StartServiceCtrlDispatcher 関数を呼び出します。その後、サービス コントロール マネージャーは、このサービス プロセスのサービス コントロール ディスパッチャーに開始要求を送信します。サービス コントロール ディスパッチャーは、開始されるサービスの ServiceMain 関数を実行する新しいスレッドを作成します。
ServiceMain 関数は、直ちに RegisterServiceCtrlHandlerEx 関数を呼び出して、コントロール要求を処理する HandlerEx 関数を指定する必要があります。次に、 SetServiceStatus 関数を呼び出して、サービス コントロール マネージャーに状態情報を送信します。これらの呼び出しの後で、サービスの初期化を完了します。 ServiceMain 関数内で別のサービスを開始しようとしないでください。
サービス コントロール マネージャー (SCM) は、サービスが SERVICE_RUNNING の状態を報告するまで待機します。この間、SCM とのやり取りを必要とするシステム内の他のコンポーネントはブロックされるため、サービスはできるだけ早くこの状態を報告することをお勧めします。一部の関数は、直接または間接的に SCM とのやり取りを必要とする場合があります。
SCM は初期化中にサービス コントロール データベースをロックします。そのため、サービスが初期化中に StartService を呼び出そうとすると、その呼び出しはブロックされます。サービスが正常に開始したことを SCM に報告した後であれば、StartService を呼び出すことができます。サービスが別のサービスの実行を必要とする場合は、必要な依存関係を設定してください。
さらに、サービスの初期化中にシステム関数を呼び出さないでください。サービスのコードがシステム関数を呼び出すのは、SERVICE_RUNNING の状態を報告した後にしてください。
ServiceMain 関数では、グローバル イベントを作成し、そのイベントに対して RegisterWaitForSingleObject 関数を呼び出してから終了します。これにより、 ServiceMain 関数を実行しているスレッドは終了しますが、サービスは終了しません。サービスを停止するときは、サービス コントロール ハンドラーが SERVICE_STOP_PENDING を指定して SetServiceStatus を呼び出し、このイベントをシグナル状態にします。スレッド プールのスレッドが待機コールバック関数を実行します。この関数では、グローバル イベントを閉じるなどのクリーンアップ処理を行い、SERVICE_STOPPED を指定して SetServiceStatus を呼び出します。サービスの停止後は、それ以上サービスのコードを実行しないでください。サービスが開始コントロールを受け取って ServiceMain が再び呼び出された場合に、競合状態が発生するおそれがあるためです。この問題は、複数のサービスが 1 つのプロセスを共有している場合に発生しやすくなります。
例
例については、 ServiceMain 関数の記述 を参照してください。
winsvc.h ヘッダーは、UNICODE プリプロセッサ定数の定義に基づいてこの関数の ANSI 版または Unicode 版を自動的に選択するエイリアスとして、LPSERVICE_MAIN_FUNCTION を定義しています。エンコードに依存しないエイリアスの使用と、エンコードに依存するコードを混在させると、不一致が生じ、コンパイル エラーや実行時エラーの原因になることがあります。詳細については、関数プロトタイプの規則 を参照してください。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)