"AND" "OR"
Главная Информер Журнал Форум

Изменение конфигурации сервиса.

Для изменения параметров установленного сервиса используются две функции ChangeServiceConfig и ChangeServiceConfig2. Ниже приведён пример, в котором сперва происходит попытка заблокировать базу данных, чтобы предотвратить запуск сервиса, пока его параметры будут изменяться. Если блокировка базы данных происходит удачно, то открывается сервис (получаем его дескриптор), изменяется его конфигурация, разблокируется база данных, а затем дескриптор сервиса закрывается. Если заблокировать базу данных не получается, то вызывается функция QueryServiceLockStatus, чтобы получить информацию о блокировке.

 

VOID ReconfigureSampleService(BOOL fDisable, LPSTR lpDesc)
{
    SC_LOCK sclLock;
    LPQUERY_SERVICE_LOCK_STATUS lpqslsBuf;
    SERVICE_DESCRIPTION sdBuf;
    DWORD dwBytesNeeded, dwStartType;

    // Необходимо заблокировать базу перед изменением настроек сервиса.

    sclLock = LockServiceDatabase(schSCManager);

    // Если база не блокируется, то выводим отчёт.

    if (sclLock == NULL)
    {
        // Выходим, если база не заблокирована другим процессом.

        if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED)
            MyErrorExit("LockServiceDatabase");

        // Выделяем буфер для детальной информации о блокировке.

        lpqslsBuf = (LPQUERY_SERVICE_LOCK_STATUS) LocalAlloc(
            LPTR, sizeof(QUERY_SERVICE_LOCK_STATUS)+256);
        if (lpqslsBuf == NULL)
            MyErrorExit("LocalAlloc");

        // Получаем и распечатываем состояние блокировки.

        if (!QueryServiceLockStatus(
            schSCManager,
            lpqslsBuf,
            sizeof(QUERY_SERVICE_LOCK_STATUS)+256,
            &dwBytesNeeded) )
            MyErrorExit("QueryServiceLockStatus");

        if (lpqslsBuf->fIsLocked)
            printf("Locked by: %s, duration: %d seconds\n",
                lpqslsBuf->lpLockOwner,
                lpqslsBuf->dwLockDuration);
        else
            printf("No longer locked\n");

        LocalFree(lpqslsBuf);
        MyErrorExit("Could not lock database");
    }

    // База заблокирована, поэтому смело можно вносить изменения.

    // Открываем дескриптор сервиса.

    schService = OpenService(
        schSCManager,           // база данных SCManager
        "Sample_Srv",           // имя сервиса
        SERVICE_CHANGE_CONFIG); // надо только изменить
    if (schService == NULL)
        MyErrorExit("OpenService");

    dwStartType = (fDisable) ? SERVICE_DISABLED :
                            SERVICE_DEMAND_START;

    // Вносим изменения.

    if (! ChangeServiceConfig(
        schService,        // дескриптор сервиса
        SERVICE_NO_CHANGE, // тип сервиса: нет изменений
        dwStartType,       // меняем тип запуска сервиса
        SERVICE_NO_CHANGE, // контроль ошибок: нет изменений
        NULL,              // путь сервиса: нет изменений
        NULL,              // принадлежность к группе: нет изменений
        NULL,              // --""--: нет изменений
        NULL,              // зависимости: нет изменений
        NULL,              // имя аккаунта: нет изменений
        NULL,              // пароль: нет изменений
        NULL) )            // отображаемое имя: нет изменений
    {
        MyErrorExit("ChangeServiceConfig");
    }
    else
        printf("ChangeServiceConfig SUCCESS\n");

    sdBuf.lpDescription = lpDesc;

    if( !ChangeServiceConfig2(
        schService,                // дескриптор сервиса
        SERVICE_CONFIG_DESCRIPTION // изменяем: описание
        &sdBuf) )                  // значение: новое описание
    {
        MyErrorExit("ChangeServiceConfig2");
    }
    else
        printf("ChangeServiceConfig2 SUCCESS\n");

    // Разблокируем базу данных.
 
    UnlockServiceDatabase(sclLock);

    // Закрываем дескриптор сервиса.

    CloseServiceHandle(schService);
}