При создании сервиса с sc.exe как передать параметры контекста?
При создании службы Windows используется:
sc create ServiceName binPath= "the path"
как аргументы могут быть переданы в коллекцию Context.Parameters класса Installer?
Мое чтение sc.exe
документация заключается в том, что такие аргументы могут быть переданы только в конце binPath
, но я не нашел пример или не смог успешно сделать это.
14 ответов
sc create <servicename> binpath= "<pathtobinaryexecutable>" [option1] [option2] [optionN]
Хитрость заключается в том, чтобы оставить пробел после = в вашем операторе create, а также использовать " " для всего, что содержит специальные символы или пробелы.
Рекомендуется указать отображаемое имя для службы, а также установить автоматический запуск для автоматического запуска. Вы можете сделать это, указав DisplayName= yourdisplayname
а также start= auto
в вашем заявлении о создании.
Вот пример:
C:\Documents and Settings\Administrator> sc create asperacentral
binPath= "C:\Program Files\Aspera\Enterprise Server\bin\Debug\asperacentral.exe"
DisplayName= "Aspera Central"
start= auto
Если это сработало, вы должны увидеть:
[SC] CreateService SUCCESS
ОБНОВЛЕНИЕ 1
Параметры для созданных сервисов имеют некоторые специфические проблемы форматирования, в частности, если команда содержит пробелы или кавычки:
Если вы хотите ввести параметры командной строки для службы, вы должны заключить всю командную строку в кавычки. (И всегда оставляйте пробел после binPath=
и перед первой цитатой, как указал миссисвад)
Итак, чтобы создать сервис для команды PATH\COMMAND.EXE --param1=xyz
вы бы использовали следующий параметр binPath:
binPath= "PATH\COMMAND.EXE --param1=xyz"
^^ ^
|| |
space quote quote
Если путь к исполняемому файлу содержит пробелы, вы должны заключить его в кавычки.
Поэтому для команды, имеющей как параметры, так и путь с пробелами, вам нужны вложенные кавычки. Вы должны экранировать внутренние кавычки с помощью обратной косой черты \ ". То же самое верно, если сами параметры содержат кавычки, вам также нужно экранировать их.
Несмотря на использование обратной косой черты в качестве escape-символов, вам не нужно избегать обычных обратных косых черт, содержащихся в пути. Это противоречит тому, как вы обычно используете обратную косую черту в качестве escape-символов.
Так для такой команды "PATH WITH SPACES \COMMAND.EXE" --param-with-quotes="a b c" --param2
:
binPath= "\"PATH WITH SPACES \COMMAND.EXE\" --param-with-quotes=\"a b c\" --param2"
^ ^ ^ ^ ^ ^ ^
| | | | | | |
opening escaped regular escaped escaped closing
quote quote backslash closing quotes quote
for for in quote for for
whole path path for path parameter whole
command command
Вот конкретный пример из документации SVNserve, который показывает все особые случаи:
sc create svnserve
binpath= "\"C:\Program Files\CollabNet Subversion Server\svnserve.exe\" --service -r \"C:\my repositories\" "
displayname= "Subversion Server" depend= Tcpip start= auto
(разрывы строк добавлены для удобства чтения, не включайте их)
Это добавило бы новый сервис с командной строкой "C:\Program Files\CollabNet Subversion Server\svnserve.exe" --service -r "C:\my repositories"
,
Итак, в заключение
- пробел после каждого параметра sc:
binpath=_
,displayname=_
а такжеdepend=_
- каждый параметр sc, содержащий пробелы, должен быть заключен в кавычки
- все дополнительные кавычки внутри binpath экранируются с помощью обратной косой черты: \ "
- все обратные слэши внутри binpath не экранированы
sc create "YOURSERVICENAME" binpath= "\"C:\Program Files (x86)\Microsoft SQL Server\MSSQL11\MSSQL\Binn\sqlservr.exe\" -sOPTIONALSWITCH" start= auto
Смотрите здесь: Изменение "Путь к исполняемому файлу" службы Windows
У меня были проблемы с тем, чтобы это работало в Windows 7. Похоже, я проигнорировал первый аргумент, который я передал, поэтому я использовал binPath= "C:\path\to\service.exe -bogusarg -realarg1 -realarg2"
и это сработало.
Я использую, чтобы просто создать его без параметров, а затем редактировать реестр HKLM\System\CurrentControlSet\Services\[YourService]
,
Это также важно, учитывая, как вы получаете доступ к аргументам в коде приложения.
В моем приложении на C# я использовал класс ServiceBase:
class MyService : ServiceBase
{
protected override void OnStart(string[] args)
{
}
}
Я зарегистрировал свой сервис, используя
sc create myService binpath= "MeyService.exe arg1 arg2"
Но я не мог получить доступ к аргументам через args
переменная, когда я запускаю его в качестве службы.
Документация MSDN предлагает не использовать метод Main для получения binPath
или же ImagePath
аргументы. Вместо этого он предлагает поместить вашу логику в OnStart
метод, а затем с помощью (C#) Environment.GetCommandLineArgs();
,
Чтобы получить доступ к первым аргументам arg1
Мне нужно сделать так:
class MyService : ServiceBase
{
protected override void OnStart(string[] args)
{
log.Info("arg1 == "+Environment.GetCommandLineArgs()[1]);
}
}
это напечатало бы
arg1 == arg1
Пример создания службы с использованием обратной косой черты с множеством двойных кавычек.
C:\Windows\system32>sc.exe create teagent binpath= "\"C:\Program Files\Tripwire\TE\Agent\bin\wrapper.exe\" -s \"C:\Program Files\Tripwire\TE\Agent\bin\agent.conf\"" DisplayName= "Tripwire Enterprise Agent"
[SC] CreateService SUCCESS
Эта команда работает:
sc create startSvn binPath= "\"C:\Subversion\bin\svnserve.exe\" --service -r \"C:\SVN_Repository\"" displayname= "MyServer" depend= tcpip start= auto
Я нашел способ использовать sc.
sc config binPath = "\" c: \ путь с пробелами в нем \service_executable.exe\" "
Другими словами, используйте \, чтобы избежать любых ", которые вы хотите пережить при переходе в реестр.
В сервере W2008 вам все еще нужно место, например
binPath= ""
, но в сервере W2019 это исправлено , и
binPath=""
работает
Я не смог решить проблему с вашими предложениями, в конце концов, с папкой x86, она работала только в Power Shell (Windows Server 2012) с использованием переменных среды:
{sc.exe create svnserve binpath= "${env:programfiles(x86)}/subversion/bin/svnserve.exe --service -r C:/svnrepositories/" displayname= "Subversion Server" depend= Tcpip start= auto}
Он не работает в Powershell и должен использовать CMD в моем случае
Если вы попробовали все вышеперечисленное и все еще не можете передать аргументы в ваш сервис, если ваш сервис написан на C/C++, вот в чем может быть проблема: когда вы запускаете свой сервис через "sc start arg1 arg2..." SC вызывает функцию ServiceMain вашего сервиса напрямую с этими аргументами. Но когда Windows запускает ваш сервис (например, во время загрузки), вызывается основная функция вашего сервиса (_tmain) с параметрами из "binPath" реестра.
Убедитесь, что в начале и конце значения binPath указаны кавычки.