Al crear un servicio con sc.exe, ¿cómo pasar los parámetros en contexto?

143

Al crear el servicio de Windows usando:

sc create ServiceName binPath= "the path"

¿Cómo se pueden pasar los argumentos a la colección Context.Parameters de la clase Installer?

Mi lectura de la sc.exedocumentación es que tales argumentos solo podrían pasarse al final binPath, pero no he encontrado un ejemplo o no he podido hacerlo con éxito.

Greg simpátrico
fuente
Un vistazo a la clave de Servicios en el Registro sugiere que los parámetros necesarios se incluyen con el valor de ImagePath, por lo que binPath= "c:\abc\def.exe /Param1=ghi"parece la idea correcta. ¿Deben escaparse las barras invertidas (es decir, "c: \\ abc \\ ...")? Lo peor, puede editar directamente el valor del Registro después si SC.EXE no puede hacerlo.
ewall
1
Renuncié a sc.exe y estoy usando installutil.exe de esta manera: Installutil.exe / ServiceName = ”TheName” / targetdir = ”C: \ TheInstallDirectory \” / PackageRoot = ”PackageRootPath”
greg simpatrico
Utilicé Installutil.exe y para tecnología anterior utilizo Instsrv.exe de Windows XP / 2003 Resource Ket.
Gary Kindel

Respuestas:

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

El truco es dejar un espacio después de = en su declaración de creación, y también usar "" para cualquier cosa que contenga caracteres o espacios especiales.

Es recomendable especificar un Nombre para mostrar para el servicio, así como establecer la configuración de inicio en automático para que se inicie automáticamente. Puede hacerlo especificando DisplayName= yourdisplaynamey start= autoen su declaración de creación.

Aquí hay un ejemplo:

C:\Documents and Settings\Administrator> sc create asperacentral 
binPath= "C:\Program Files\Aspera\Enterprise Server\bin\Debug\asperacentral.exe" 
DisplayName= "Aspera Central" 
start= auto

Si esto funcionó, debería ver:

[SC] CreateService SUCCESS

ACTUALIZACIÓN 1

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

Mhmd
fuente
39
Tenga en cuenta que el espacio después de binPath = ( binPath= "C:\...") debe estar presente, de lo contrario, esto no funcionará.
Onion-Knight
1
start= autoes importante, por lo que después de reiniciar el servicio se iniciará automáticamente. Muy bueno en caso de que el usuario final no sea un experto
LaBracca
21
Además, si necesita pasar parámetros adicionales en el binPathque requieren comillas, deben escaparse ( \") ejemplo: si la ruta fuera c:\some long path\some.exe "first argument", tendría que serlobinPath= "\"c:\some long path\some.exe\" \"first argument\""
Lankymart
1
Si no tiene un espacio después del "=" en sus argumentos (como binPath= ...y DisplayName= ...; en mi caso olvidé el "=" después de DisplayName), la consola imprimirá las instrucciones de uso del createcomando; como: DESCRIPTION: Creates a service entry... USAGE: sc <server> create....etc
The Red Pea
3
Los espacios después de "=" son muy importantes
ErisoHV
152

Los parámetros para los servicios creados tienen algunos problemas de formateo peculiares, en particular si el comando incluye espacios o comillas:

Si desea ingresar parámetros de línea de comando para el servicio, debe encerrar la línea de comando completa entre comillas. (Y siempre deje un espacio después binPath=y antes de la primera cita, como señaló mrswadge)

Entonces, para crear un servicio para el comando PATH\COMMAND.EXE --param1=xyz , usaría el siguiente parámetro binPath:

binPath= "PATH\COMMAND.EXE --param1=xyz"
        ^^                             ^
        ||                             |
  space    quote                     quote

Si la ruta al ejecutable contiene espacios , debe encerrar la ruta entre comillas.

Así que por un comando que tiene dos parámetros y un camino con espacios, necesita comillas anidadas . Tienes que escapar de las comillas internas con barras invertidas \". Lo mismo ocurre si los parámetros en sí contienen comillas, también deberá escapar de ellos.

A pesar de utilizar las barras diagonales inversas como caracteres de escape, no tiene que escapar de las barras diagonales inversas normales contenidas en la ruta. Esto es contrario a la forma en que normalmente utiliza barras invertidas como caracteres de escape.

Entonces, para un comando como
"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

Aquí hay un ejemplo concreto de la documentación de SVNserve, que muestra todos los casos especiales:

sc create svnserve 
   binpath= "\"C:\Program Files\CollabNet Subversion Server\svnserve.exe\" --service -r \"C:\my repositories\"  "
   displayname= "Subversion Server" depend= Tcpip start= auto 

(se agregan saltos de línea para facilitar la lectura, no los incluya)

Esto agregaría un nuevo servicio con la línea de comando "C:\Program Files\CollabNet Subversion Server\svnserve.exe" --service -r "C:\my repositories".

Entonces en resumen

  • espacio después de cada parámetro sc: binpath=_, displayname=_ydepend=_
  • cada parámetro sc que contiene espacios debe estar entre comillas
  • todas las citas adicionales dentro del binpath se escapan con barras invertidas: \"
  • todas las barras invertidas dentro del binpath no se escapan
HugoRune
fuente
77
Descubrí que era importante asegurarse de que haya un espacio entre binPath = y el valor "myservice.exe". es decir binPath= "myservice.exe. El intérprete de línea de comando debe esperar esto y requerir que el comando se convierta en token utilizando el espacio como delimitador.
mrswadge
Lo intenté de esta manera y funcionó. SC.EXE "\\ ServerName" Crear "ServiceName" BinPath = "SampleService.exe"
Sai
5

Tuve problemas para que esto funcionara en Windows 7. Parecía ignorar el primer argumento que transmití, así que lo usé binPath= "C:\path\to\service.exe -bogusarg -realarg1 -realarg2"y funcionó.

Craig Carpenter
fuente
4

Solía ​​crearlo sin parámetros y luego editar el registro HKLM\System\CurrentControlSet\Services\[YourService].

Tony
fuente
2

Este comando funciona:

sc create startSvn binPath= "\"C:\Subversion\bin\svnserve.exe\" --service -r \"C:\SVN_Repository\"" displayname= "MyServer" depend= tcpip start= auto
usuario2535091
fuente
2

También es importante tener en cuenta cómo accede a los Argumentos en el código de la aplicación.

En mi aplicación C # utilicé la clase ServiceBase:

 class MyService : ServiceBase
{

    protected override void OnStart(string[] args)
    {
       }
 }

Registré mi servicio usando

sc create myService binpath = "MeyService.exe arg1 arg2"

Pero no pude acceder a los argumentos a través de la argsvariable cuando lo ejecuté como un servicio.

La documentación de MSDN sugiere no usar el método Main para recuperar los argumentos binPatho ImagePath. En cambio, sugiere colocar su lógica en el OnStartmétodo y luego usar (C #) Environment.GetCommandLineArgs();.

Para acceder a los primeros argumentos arg1tengo que hacer así:

class MyService : ServiceBase
 {

    protected override void OnStart(string[] args)
    {

                log.Info("arg1 == "+Environment.GetCommandLineArgs()[1]);

       }
 }

esto imprimiría

       arg1 == arg1
Panciz
fuente
También puede obtener su arg1 y arg2 del parámetro args en el método Main.
Wojciech Mikołajewicz
1

Encontré una manera de usar sc.

sc config binPath = "\" c: \ ruta con espacios en ella \ service_executable.exe \ ""

En otras palabras, use \ para escapar de cualquier "'s que desee para sobrevivir al tránsito hacia el registro.

Rem Onyshczak
fuente
1

Un ejemplo de creación de servicio del uso de barras invertidas con muchas comillas dobles.

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
Nash A
fuente
0

Asegúrese de tener comillas al principio y al final de su valor binPath.

cripox
fuente
1
Dada una ruta "c: \ abc \ def.exe", intenté pasar en Param1 = "ghi" de esta manera: binPath = "c: \ abc \ def.exe / Param1 = ghi". Pero no funciona ...
simpatric greg
0

No pude manejar el problema con sus propuestas, al final con la carpeta x86 solo funcionó en Power Shell (Windows Server 2012) usando variables de entorno:

{sc.exe create svnserve binpath= "${env:programfiles(x86)}/subversion/bin/svnserve.exe --service -r C:/svnrepositories/"   displayname= "Subversion Server" depend= Tcpip start= auto}
g0r1lla
fuente
0

Si probó todo lo anterior y aún no puede pasar argumentos a su servicio, si su servicio fue escrito en C / C ++, esto es lo que podría ser el problema: cuando inicia su servicio a través de "sc start arg1 arg2 ..." , SC llama a la función ServiceMain de su servicio directamente con esos argumentos. Pero cuando Windows inicia su servicio (en el momento del arranque, por ejemplo), se llama a la función principal de su servicio (_tmain), con parámetros del "binPath" del registro.

Rio Azul
fuente
0

no funciona en Powershell y debería usar CMD en mi caso

Guillermo
fuente
fijo en PowerShell 5.1
Oetzi