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