При создании службы с помощью sc.exe, как передать параметры контекста?

148

При создании службы Windows с использованием:

sc create ServiceName binPath= "the path"

как можно передать аргументы в коллекцию Context.Parameters класса установщика?

Я читал sc.exeдокументацию, что такие аргументы можно было передать только в конце binPath, но я не нашел примера и не смог успешно это сделать.

сочувствующий Грег
источник
Взглянув на ключ Services в реестре, можно предположить, что все необходимые параметры включены в значение ImagePath, поэтому ваша binPath= "c:\abc\def.exe /Param1=ghi"идея кажется правильной. Нужно ли экранировать обратную косую черту (например, "c: \\ abc \\ ...")? Хуже всего то, что вы могли напрямую редактировать значение реестра после этого, если SC.EXE не может этого сделать.
ewall 08
1
Я отказался от sc.exe и использую installutil.exe следующим образом: Installutil.exe / ServiceName = ”TheName” / targetdir = ”C: \ TheInstallDirectory \” / PackageRoot = ”PackageRootPath”
сочувствующий greg
Я использовал Installutil.exe, а для более старых технологий я использую Instsrv.exe из Windows XP / 2003 Resource Ket.
Гэри Киндел

Ответы:

261
sc create <servicename> binpath= "<pathtobinaryexecutable>" [option1] [option2] [optionN]

Уловка состоит в том, чтобы оставить пробел после = в вашем операторе создания, а также использовать "" для всего, что содержит специальные символы или пробелы.

Рекомендуется указать отображаемое имя для службы, а также установить для параметра запуска значение авто, чтобы он запускался автоматически. Вы можете сделать это, указав 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

http://support.microsoft.com/kb/251192

МГМД
источник
41
Имейте в виду, что после binPath = ( binPath= "C:\...") должен быть пробел , иначе это не сработает.
Onion-Knight
1
start= autoявляется важным, поэтому после перезагрузки служба запустится автоматически. Очень хорошо, если конечный пользователь не является экспертом
ЛаБракка
23
Также, если вам нужно передать дополнительные параметры в те, binPathкоторые требуют кавычек, они должны быть экранированы ( \") пример: если бы путь был, c:\some long path\some.exe "first argument"он должен был бы бытьbinPath= "\"c:\some long path\some.exe\" \"first argument\""
Lankymart
1
Если у вас нет пробела после «=» в ваших аргументах (например, binPath= ...и DisplayName= ...; в моем случае я забыл «=» после DisplayName), тогда консоль напечатает инструкции по использованию для createкоманды; например: DESCRIPTION: Creates a service entry... USAGE: sc <server> create....etc
The Red Pea
3
Пробелы после "=" очень важны
ErisoHV
156

Параметры для созданных сервисов имеют некоторые специфические проблемы с форматированием, в частности, если команда включает пробелы или кавычки:

Если вы хотите ввести параметры командной строки для службы, вы должны заключить всю командную строку в кавычки. (И всегда оставляйте пробел после 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 не экранируются
HugoRune
источник
7
Я обнаружил, что важно убедиться, что между binPath = и значением myservice.exe есть пробел. то есть binPath= "myservice.exe. Интерпретатор командной строки должен ожидать этого и требовать токенизации команды с использованием пробела в качестве разделителя.
mrswadge
Я пробовал этот способ, и это сработало. SC.EXE "\\ ServerName" Create "ServiceName" BinPath = "SampleService.exe"
Сай
5

У меня были проблемы с тем, чтобы заставить это работать в Windows 7. Казалось, что первый аргумент, который я передал, игнорировался, поэтому я использовал, binPath= "C:\path\to\service.exe -bogusarg -realarg1 -realarg2"и он сработал.

Крейг Карпентер
источник
4

Я использую просто создавать его без параметров, а потом редактировать реестр HKLM\System\CurrentControlSet\Services\[YourService].

Тони
источник
2

Эта команда работает:

sc create startSvn binPath= "\"C:\Subversion\bin\svnserve.exe\" --service -r \"C:\SVN_Repository\"" displayname= "MyServer" depend= tcpip start= auto
user2535091
источник
2

Также важно учитывать, как вы получаете доступ к аргументам в коде приложения.

В моем приложении на 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
Panciz
источник
Вы также можете получить свои arg1 и arg2 из параметра args в методе Main.
Wojciech Mikołajewicz
1

Я нашел способ использовать sc.

sc config binPath = "\" c: \ путь с пробелами в нем \ service_executable.exe \ ""

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

Рем Оныщак
источник
1

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

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
Нэш А
источник
0

Убедитесь, что в начале и в конце значения binPath есть кавычки.

крипокс
источник
1
Учитывая путь «c: \ abc \ def.exe», я попытался передать Param1 = «ghi» следующим образом: binPath = «c: \ abc \ def.exe / Param1 = ghi». Но не работоспособный ...
сочувствующий greg
0

Я не мог решить проблему с вашими предложениями, в конце с папкой 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}
g0r1lla
источник
0

Если вы попробовали все вышеперечисленное и по-прежнему не можете передавать аргументы своей службе, если ваша служба была написана на C / C ++, вот в чем может быть проблема: когда вы запускаете службу с помощью «sc start arg1 arg2 ...» , SC вызывает функцию ServiceMain вашего сервиса напрямую с этими аргументами. Но когда Windows запускает вашу службу (например, во время загрузки), вызывается основная функция вашей службы (_tmain) с параметрами из «binPath» реестра.

BlueRiver
источник
0

он не работает в Powershell и должен использовать CMD в моем случае

Уильям
источник
исправлено в PowerShell 5.1
oetzi