LPSERVICE_MAIN_FUNCTIONA
コールバックシグネチャ
void LPSERVICE_MAIN_FUNCTIONA(
DWORD dwNumServicesArgs,
LPSTR* lpServiceArgVectors
);パラメーター
| フィールド | 型 | 説明 |
|---|---|---|
| dwNumServicesArgs | DWORD | lpServiceArgVectors 配列に含まれる引数の数。 |
| lpServiceArgVectors | LPSTR* | サービスを開始した 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)