Как добавить зависимость для службы Windows ПОСЛЕ установки службы

Вопрос или проблема

У меня есть служба Windows, которая использует базу данных SQL Server. Я не имею контроля над установкой службы, но хотел бы добавить зависимость к этой службе, чтобы она запускалась после того, как SQL Server уже запущен. (SQL Server работает на той же машине, что и рассматриваемая служба)

Есть ли инструмент для добавления зависимости или, возможно, редактирование реестра напрямую?

Это также можно сделать через с повышенными правами командную строку, используя команду sc. Синтаксис следующий:

sc config [service name] depend= <Dependencies(separated by / (forward slash))>

Примечание: Пробел есть после знака равенства, и его нет перед ним.

Предупреждение: Параметр depend= перезапишет существующий список зависимостей, а не добавит к нему. Например, если ServiceA уже зависит от ServiceB и ServiceC, и вы выполняете depend= ServiceD, теперь ServiceA будет зависеть только от ServiceD. (Спасибо Matt!)

Примеры

Зависимость от одной другой службы:

sc config ServiceA depend= ServiceB

Вышеуказанное означает, что ServiceA не запустится, пока не будет запущена ServiceB. Если вы остановите ServiceB, ServiceA автоматически остановится.

Зависимость от нескольких других служб:

sc config ServiceA depend= ServiceB/ServiceC/ServiceD/"Service Name With Spaces"

Вышеуказанное означает, что ServiceA не запустится, пока не будут запущены ServiceB, ServiceC и ServiceD. Если вы остановите любую из служб ServiceB, ServiceC или ServiceD, ServiceA автоматически остановится.

Чтобы удалить все зависимости:

sc config ServiceA depend= /

Чтобы просмотреть текущие зависимости:

sc qc ServiceA

Вы можете добавить зависимости службы, добавив значение “DependOnService” в реестре с помощью команды regedit, службы можно найти по пути HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<Service name>.

Подробности можно найти в статье 193888 на сайте Microsoft.

Чтобы добавить зависимость:

  1. Выберите подраздел службы, нажмите правой кнопкой мыши на имени службы и выберите “Новый” -> “Множественная строка” (REG_MULTI_SZ)

    введите описание изображения здесь

  2. Создайте новое значение с именем “DependOnService” (без кавычек) и нажмите OK.

    введите описание изображения здесь

  3. Когда появится окно ввода данных, введите имя или имена служб, которые вы предпочитаете запускать перед этой службой, с одной записью на каждой строке, и нажмите OK.

Я искал чисто метод с помощью PowerShell (без regedit или sc.exe), который может работать на 2008R2/Win7 и новее, и пришел к следующему:

Простой способ – сделать regedit с помощью PowerShell:

Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\LanmanWorkstation' -Name DependOnService -Value @('Bowser','MRxSmb20','NSI')

Или используя WMI:

$DependsOn = @('Bowser','MRxSmb20','NSI','') #оставьте пустой элемент массива в конце
$svc = Get-WmiObject win32_Service -filter "Name="LanmanWorkstation""
$svc.Change($null,$null,$null,$null,$null,$null,$null,$null,$null,$null,$DependsOn)

Метод Change класса Win32_Service помог указать на решение:

uint32 Change(
[in] string  DisplayName,
[in] string  PathName,
[in] uint32  ServiceType,
[in] uint32  ErrorControl,
[in] string  StartMode,
[in] boolean DesktopInteract,
[in] string  StartName,
[in] string  StartPassword,
[in] string  LoadOrderGroup,
[in] string  LoadOrderGroupDependencies[],
[in] string  ServiceDependencies[]
);

Я написал простое .NET приложение для управления зависимостями служб, если вас это заинтересует. Это бесплатно.

http://webpages.charter.net/bushman4/servicedependencymanager.html

В C++ (ATL) я сделал следующее

bool ModifyDependOnService(void)
{
  CRegKey R;
  if (ERROR_SUCCESS == R.Open(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\services\\MyService"))
  {
    bool depIsThere = false;

    // определяем, установлена ли другая служба, если да, то добавляем в список зависимостей.
    SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
    if (hSCManager)
    {
      SC_HANDLE hService = OpenService(hSCManager, L"OtherService", SERVICE_QUERY_STATUS);
      if (hService)
      {
        depIsThere = true;
        CloseServiceHandle(hService);
      }
      CloseServiceHandle(hSCManager);
    }

    std::wstring key = L"DependOnService";
    if (depIsThere )
    {
      const wchar_t deps[] = L"RPCSS\0OtherService\0";
      R.SetValue(key.c_str(), REG_MULTI_SZ, deps, sizeof(deps));
    }

    R.Close();
    return true;
  }
  return false;
}

Создал пакет “svcDependDelAdd.BAT” для удаления и/или добавления зависимости к службе, он не добавит, если не существует. Можно вызвать. Преимущества над принятым ответом в том, что он не удаляет другие зависимости, просто удаляет (или добавляет) нужную. Включена помощь:

@echo off
set PARAM=%* _& REM _ избегайте, если PARAM пустой при отсутствии параметров, %* это остальные параметры
rem https://serverfault.com/questions/24821/how-to-add-dependency-on-a-windows-service-after-the-service-is-installed/1165202#1165202

IF not "%PARAM:/noh=%"=="%PARAM%" goto :noHelp
echo .
echo . svcDependDelAdd v24.0915
echo .   Удаляет и/или добавляет зависимую службу, можно указать "none":
echo .
echo . svcDependDelAdd targetSvc [[dependSvcToDelete] dependSvcToAdd] [/switches]
echo .
echo .
echo . переключатели:
echo .   /noHelp: не показывать это
echo .   /noPause: в конце
echo .
echo . Примеры:
echo . svcDependDelAdd nlaSvc /noh/nop   (список зависимостей nlaSvc разделен на \0^)
echo . svcDependDelAdd nlaSvc eventLog   (Удаляет зависимость eventLog от nlaSvc^)
echo . svcDependDelAdd none eventLog     (Добавляет зависимость eventLog к nlaSvc^)
echo .
echo .
:noHelp

setlocal enableextensions enableDelayedExpansion & REM получить значение переменной на Exec с !varNm!
  rem Целевая служба, напр.: "nlaSvc"; или "aelookupsvc" не имеет зависимостей
set "targSvc=%1"
  rem установите на "none", если это пусто, или если оно имеет слэш {/ switch}
IF not "!targSvc:/=!"=="!targSvc!" set "targSvc=none"
  rem Зависимость для удаления, может быть пустым/недействительным/неопределенным, напр.: "Eventlog"
set "delDep=%2"
IF not "!delDep:/=!"=="!delDep!" set "delDep=none"
  rem Зависимость для добавления, может быть пустым/нет/неопределенным, не добавит несуществующую службу
set "addDep=%3"
IF not "!addDep:/=!"=="!addDep!" set "addDep=none"
  rem echo  "%targSvc%" "%delDep%" "%addDep%"

  rem проверить существование услуги
if not "!targSvc:none=!"=="" ( rem не "none" и не пуст
  sc qc "!targSvc!" >nul 2>&1
  if errorlevel 1 ( set errMsg=Svc "%targSvc%" не найден & goto :error )
) else ( set errMsg=Служба не указана & goto :error )

  rem Получить список зависимостей %targSvc%
set depList=\0
for /f "usebackq tokens=1,2,*" %%x in (`reg query HKLM\System\CurrentControlSet\Services\%targSvc% /v DependOnService`) do (
  if "%%y"=="REG_MULTI_SZ" set "depList=%%z\0"
) & rem endList

  rem удалить: найдите его и установите новый список зависимостей
set "newDep=!depList!" & rem новый список зависимостей для установки
if "!depList!"=="\0" (
  echo %targSvc% зависимости не найдены!
) else (
  echo "%targSvc%" список зависимостей: "!depList!"
    rem удалить зависимость из нового списка
  if not "!delDep:none=!"=="" (
    set "newDep=!depList:%delDep%\0=!"
    rem set "newDep=!newDep:\0\0=\0!"
    if "!newDep!"=="!depList!" (
      echo   "%delDep%" не найден в "%targSvc%"
    ) else echo   удалить найденный "%delDep%"
  ) & rem delDep
)

  rem добавить: найти и установить новый список зависимостей
if not "!addDep:none=!"=="" if "!newDep:%addDep%\0=!"=="!newDep!" (
  rem не нет/пусто, и не уже присутствует в новом списке
  reg query HKLM\System\CurrentControlSet\Services\%addDep% 1>nul 2>&1
  if errorlevel 1 ( echo   добавить "%addDep%" не найден
  ) else (
    echo   добавить найденный "%addDep%"
    set "newDep=!newDep!%addDep%\0" & rem добавить в список
    if "!depList!"=="\0" set "newDep=%addDep%" & rem оригинальный список был пустой
  )
) else echo   добавить "%addDep%" уже присутствует

  rem записать новый список зависимостей
if "!newDep!"=="!depList!" ( echo Нечего делать... ) else (
  echo список новых зависимостей "!newDep!" ...
  reg add HKLM\System\CurrentControlSet\Services\%targSvc% /v DependOnService /t REG_MULTI_SZ /d "!newDep!" /f
  if errorlevel 1 ( set errMsg=не удалось обновить ключ зависимости "%targSvc%" DependOnService & goto :error )
)

echo -ГОТОВО-
goto :fin

:error
echo\ Ошибка: !errMsg!

:fin
echo\
IF "%PARAM:/nop=%"=="%PARAM%" pause

.

Ответ или решение

Как добавить зависимость к Службе Windows после её установки

Введение зависимости для службы Windows может быть необходимым шагом для гарантии, что ваша служба запускается после всех необходимых компонентов, например, после SQL Server, который используется вашей службой и находится на одной машине. Есть несколько подходов к решению этой задачи, включая использование командной строки, правки реестра и написание скриптов на PowerShell. Рассмотрим каждый из них подробнее.

Теория

Прежде всего, следует понять, что служба Windows может зависеть от одной или нескольких других служб. Это обозначается свойством DependOnService, и позволяет гарантировать, что ваша служба не начнется до тех пор, пока все службы, от которых она зависит, не будут активированы. Это полезно в случаях, когда порядок запуска критически важен для корректной работы программы.

Пример

  1. Использование инструмента командной строки sc:
    Команда sc config позволяет вам настроить параметры уже существующей службы. Исправление зависимости выполняется как:

    sc config [имя вашей службы] depend= [список зависимостей через /]

    Например, если ваша служба называется ServiceA, и вы хотите, чтобы она зависела от MSSQLSERVER, вы можете использовать:

    sc config ServiceA depend= MSSQLSERVER

    Обратите внимание на важность пробела после depend= и отсутствие пробела перед ним. Учтите, что эта команда перезаписывает существующий список зависимостей, так что если ваша служба уже имеет другие зависимости, их потребуется указать повторно.

  2. Редактирование реестра Windows:
    Вы можете вручную внести изменения в реестр для добавления зависимости. Шаги следующие:

    • Запустите regedit от имени администратора.
    • Перейдите в раздел HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\[имя вашей службы].
    • Найдите (или создайте) значение DependOnService (типа REG_MULTI_SZ).
    • Внесите имена всех необходимых служб в отдельные строки для каждой зависимости.

    Этот метод дает больше контроля и позволяет избежать перезаписывания других существующих зависимостей.

  3. Скрипты PowerShell:
    PowerShell предлагает гораздо более гибкие инструменты для администрирования систем. Используйте командлет Set-ItemProperty для непосредственной работы с реестром:

    Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\[имя вашей службы]' -Name DependOnService -Value @('MSSQLSERVER')

    Или вы можете воспользоваться объектами WMI для обновления зависимостей программно:

    $DependsOn = @('MSSQLSERVER', '')
    $svc = Get-WmiObject win32_Service -filter "Name='[имя вашей службы]'"
    $svc.Change($null, $null, $null, $null, $null, $null, $null, $null, $null, $null, $DependsOn)

Применение

После того как вы выбрали подходящий метод, можно приступить к внесению изменений. Обязательно убедитесь, что у вас есть права администратора на машине, на которой производится изменение. Резервное копирование текущих настроек реестра может быть хорошей практикой, чтобы избежать случайных ошибок.

На практике, для обеспечения минимального простоя служб, рекомендуется использовать PowerShell, так как он предоставляет наибольшую гибкость и возможность интеграции с другими административными задачами и расписаниями. Однако, для более быстрого развертывания изменений на нескольких машинах, написание скриптов на основе sc или правка реестра могут стать эффективными решениями.

Заключение

Изменение зависимостей службы Windows после её установки — это несложный, но очень важный процесс, который может иметь значительное влияние на работу вашего приложения, особенно в крупных системах, где несколько служб работают в тесной интеграции. Выбор определенного метода зависит от ваших потребностей и уровня доступа в системе, но следуя данным указаниям, вы сможете осуществить необходимые изменения надежно и безопасно.

Оцените материал
Добавить комментарий

Капча загружается...