次の方法で共有


ホスト コンピューターへのサービスのインストール

次のコード例は、ディレクトリ対応サービスをホスト コンピューターにインストールする基本的な手順を示しています。 次の操作を実行します。

  1. OpenSCManager 関数を呼び出して、ローカル コンピューター上のサービス コントロール マネージャー (SCM) へのハンドルを開きます。
  2. CreateService 関数を呼び出して、SCM データベースにサービスをインストールします。 この呼び出しでは、サービスのログオン アカウントとパスワード、サービスの実行可能ファイル、およびサービスに関するその他の情報を指定します。 指定 ログオン アカウントが無効な場合、CreateService は失敗します。 ただし、CreateService は、パスワードの有効性を確認しません。 また、アカウントがローカル コンピューターでサービスとしてのログオンを行っていることを確認しません。 詳細については、「ホスト コンピューターでのサービスとしてのログオン権限の付与」を参照してください。
  3. サービスの ScpCreate サブルーチンを呼び出して、サービスのこのインスタンスの場所を公開するサービス接続ポイント オブジェクト (SCP) をディレクトリに作成します。 詳細については、「クライアントがサービス接続ポイントを検索して使用する方法」を参照してください。 また、このルーチンは、サービスのバインディング情報を SCP に格納し、SCP に ACE を設定して、サービスが実行時にアクセスできるようにし、SCP の識別名をローカル レジストリにキャッシュして、新しい SCP の識別名を返します。
  4. サービスのクラス文字列と SCP の識別名を使用してサービス プリンシパル名 (SPN) を構成するサービスの SpnCompose サブルーチンを呼び出します。 詳細については、「SCP を使用したサービスの SPN の作成」を参照してください。 SPN は、サービスのこのインスタンスを一意に識別します。
  5. サービスのログオン アカウントに関連付けられているアカウント オブジェクトに SPN を登録するサービスの SpnRegister サブルーチンを呼び出します。 詳細については、「サービスの SPN の登録」を参照してください。 SPN を登録すると、クライアント アプリケーションでサービスを認証できます。

このコード例は、ログオン アカウントがローカル ユーザー アカウントかドメイン ユーザー アカウントか LocalSystem アカウントかに関係なく、正しく機能します。 ドメイン ユーザー アカウントの場合、szServiceAccountSAM パラメーターにはアカウントの Domain**\**UserName 名が含まれており、szServiceAccountDN パラメーターにはディレクトリ内のユーザー アカウント オブジェクトの識別名が含まれます。 LocalSystem アカウントの場合、szServiceAccountSAMszPassword は null szServiceAccountSN は、ディレクトリ内のローカル コンピューターのアカウント オブジェクトの識別名です。 szServiceAccountSAM がローカル ユーザー アカウント (名前の形式は ".\UserName") を指定した場合、コード例では、ローカル ユーザー アカウントに対する相互認証がサポートされていないため、SPN 登録をスキップします。

既定のセキュリティ構成では、ドメイン管理者のみがこのコードを実行できます。

また、このコード例は、記述されているように、サービスがインストールされているコンピューターで実行する必要があることに注意してください。 そのため、通常は、スキーマの拡張、UI の拡張、またはグループ ポリシーの設定を行う、サービス インストール コード (存在する場合) とは別のインストール実行可能ファイルに含まれます。 これらの操作では、フォレスト全体のサービス コンポーネントがインストールされますが、このコードでは 1 台のコンピューターにサービスがインストールされます。

void InstallServiceOnLocalComputer(
            LPTSTR szServiceAccountDN,  // Distinguished name of logon account.
            LPTSTR szServiceAccountSAM, // SAM name of logon account.
            LPTSTR szPassword)          // Password of logon account.
{
SC_HANDLE   schService = NULL;
SC_HANDLE   schSCManager = NULL;
TCHAR szPath[512];
LPTSTR lpFilePart;
TCHAR szDNofSCP[MAX_PATH];
TCHAR szServiceClass[]=TEXT("ADSockAuth");
 
DWORD dwStatus;
TCHAR **pspn=NULL;
ULONG ulSpn=1;
 
// Get the full path of the service's executable.
// The code example assumes that the executable is in the current directory.
dwStatus = GetFullPathName(TEXT("service.exe"), 512, szPath, &lpFilePart);
if (dwStatus == 0) {
    _tprintf(TEXT("Unable to install %s - %s\n"), 
            TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
    return;
}
_tprintf(TEXT("path of service.exe: %s\n"), szPath);
 
// Open the Service Control Manager on the local computer.
schSCManager = OpenSCManager(
                NULL,                   // Computer (NULL == local)
                NULL,                   // Database (NULL == default)
                SC_MANAGER_ALL_ACCESS   // Access required
                );
if (! schSCManager) {
    _tprintf(TEXT("OpenSCManager failed - %s\n"), 
                   GetLastErrorText(szErr,256));
    goto cleanup;
}
        
// Install the service in the SCM database.
schService = CreateService(
            schSCManager,               // SCManager database
            TEXT(SZSERVICENAME),        // Name of service
            TEXT(SZSERVICEDISPLAYNAME), // Name to display
            SERVICE_ALL_ACCESS,         // Desired access
            SERVICE_WIN32_OWN_PROCESS,  // Service type
            SERVICE_DEMAND_START,       // Start type
            SERVICE_ERROR_NORMAL,       // Error control type
            szPath,                     // Service binary
            NULL,                       // No load ordering group
            NULL,                       // No tag identifier
            TEXT(SZDEPENDENCIES),       // Dependencies
            szServiceAccountSAM,        // Service account
            szPassword);                // Account password
if (! schService) {
    _tprintf(TEXT("CreateService failed - %s\n"), 
                   GetLastErrorText(szErr,256));
    goto cleanup;
}
 
_tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
 
// Create the service's Service Connection Point (SCP).
dwStatus = ScpCreate(
        2000,                 // Service default port number
        szServiceClass,       // Specifies the service class string
        szServiceAccountSAM,  // SAM name of logon account for ACE
        szDNofSCP             // Buffer returns the DN of the SCP
        );
if (dwStatus != 0) {
    _tprintf(TEXT("ScpCreate failed: %d\n"), dwStatus );
    DeleteService(schService);
    goto cleanup;
}
 
// Compose and register a service principal name for this service.
// This is performed on the install path because this requires elevated
// privileges for updating the directory.
// If a local account of the format ".\user name", skip the SPN.
if ( szServiceAccountSAM[0] == '.' ) 
{
    _tprintf(TEXT("Do not register SPN for a local account.\n"));
    goto cleanup;
}
 
dwStatus = SpnCompose(
        &pspn,            // Receives pointer to the SPN array.
        &ulSpn,           // Receives number of SPNs returned.
        szDNofSCP,        // Input: DN of the SCP.
        szServiceClass);  // Input: the service's class string.
 
if (dwStatus == NO_ERROR) 
    dwStatus = SpnRegister(
        szServiceAccountDN,  // Account on which SPNs are registered.
        pspn,                // Array of SPNs to register.
        ulSpn,               // Number of SPNs in array.
        DS_SPN_ADD_SPN_OP);  // Operation code: Add SPNs.
 
if (dwStatus != NO_ERROR) 
{
    _tprintf(TEXT("Failed to compose SPN: Error was %X\n"), 
                  dwStatus);
    DeleteService(schService);
    ScpDelete(szDNofSCP, szServiceClass, szServiceAccountDN);
    goto cleanup;
}
 
cleanup:
if (schSCManager)
    CloseServiceHandle(schSCManager);
if (schService)
    CloseServiceHandle(schService);
DsFreeSpnArray(ulSpn, pspn);
return;
}

前のコード例の詳細については、「SCP を使用してサービスの SPN を作成する と、サービス の SPN を登録するを参照してください。