Lors de la création d'un service avec sc.exe, comment passer des paramètres de contexte?

143

Lors de la création du service Windows en utilisant:

sc create ServiceName binPath= "the path"

comment les arguments peuvent-ils être passés à la collection Context.Parameters de la classe Installer?

Ma lecture de la sc.exedocumentation est que de tels arguments ne pouvaient être transmis qu'à la fin de binPath, mais je n'ai pas trouvé d'exemple ou n'ai pas pu le faire avec succès.

greg sympatrique
la source
Un coup d'œil sur la clé Services dans le registre suggère que tous les paramètres nécessaires sont inclus avec la valeur ImagePath, donc vous binPath= "c:\abc\def.exe /Param1=ghi"semblez être la bonne idée. Les barres obliques inverses doivent-elles être échappées (par exemple "c: \\ abc \\ ...")? Pire encore, vous pouvez modifier directement la valeur du registre par la suite si SC.EXE ne peut pas le faire.
ewall
1
J'ai abandonné sc.exe et j'utilise installutil.exe comme ceci: Installutil.exe / ServiceName = "TheName" / targetdir = "C: \ TheInstallDirectory \" / PackageRoot = "PackageRootPath"
sympatric greg
J'ai utilisé Installutil.exe et pour une technologie plus ancienne, j'utilise Instsrv.exe de Windows XP / 2003 Resource Ket.
Gary Kindel

Réponses:

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

L'astuce consiste à laisser un espace après le = dans votre instruction create, et également à utiliser "" pour tout ce qui contient des caractères spéciaux ou des espaces.

Il est conseillé de spécifier un nom d'affichage pour le service ainsi que de définir le paramètre de démarrage sur auto afin qu'il démarre automatiquement. Vous pouvez le faire en spécifiant DisplayName= yourdisplaynameet start= autodans votre instruction create.

Voici un exemple:

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 cela a fonctionné, vous devriez voir:

[SC] CreateService SUCCESS

MISE À JOUR 1

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

Mhmd
la source
39
Gardez à l'esprit que l'espace après binPath = ( binPath= "C:\...") doit être présent, sinon cela ne fonctionnera pas.
Onion-Knight
1
start= autoest important, donc après le redémarrage, le service sera automatiquement démarré. Très bien au cas où l'utilisateur final ne serait pas un expert
LaBracca
21
Aussi si vous avez besoin de passer des paramètres supplémentaires dans le binPathqui nécessitent des guillemets, ils doivent être échappés ( \") exemple: si le chemin était, c:\some long path\some.exe "first argument"il devrait êtrebinPath= "\"c:\some long path\some.exe\" \"first argument\""
Lankymart
1
Si vous n'avez pas d'espace après le "=" dans vos arguments (comme binPath= ...et DisplayName= ...; dans mon cas, j'ai oublié le "=" après DisplayName), alors la console imprimera les instructions d'utilisation de la createcommande; comme: DESCRIPTION: Creates a service entry... USAGE: sc <server> create....etc
The Red Pea
3
Les espaces après le "=" sont très importants
ErisoHV
152

Les paramètres des services créés présentent des problèmes de format particuliers, en particulier si la commande comprend des espaces ou des guillemets:

Si vous souhaitez entrer des paramètres de ligne de commande pour le service, vous devez mettre toute la ligne de commande entre guillemets. (Et laissez toujours un espace après binPath=et avant la première citation, comme l'a souligné mrswadge)

Ainsi, pour créer un service pour la commande, PATH\COMMAND.EXE --param1=xyz vous utiliseriez le paramètre binPath suivant:

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

Si le chemin d' accès à l'exécutable contient des espaces , vous devez mettre le chemin entre guillemets.

Donc, pour une commande qui a à la fois des paramètres et un chemin avec des espaces, vous avez besoin de guillemets imbriqués . Vous devez échapper les guillemets intérieurs avec des barres obliques inverses \". Il en va de même si les paramètres eux-mêmes contiennent des guillemets, vous devrez également les échapper.

Malgré l'utilisation de barres obliques inverses comme caractères d'échappement, vous n'avez pas besoin d'échapper aux barres obliques inverses régulières contenues dans le chemin. Ceci est contraire à la façon dont vous utilisez normalement des barres obliques inverses comme caractères d'échappement.

Donc pour une commande comme
"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

Voici un exemple concret de la documentation SVNserve, qui montre tous les cas particuliers:

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

(les sauts de ligne sont ajoutés pour plus de lisibilité, ne les incluez pas)

Cela ajouterait un nouveau service avec la ligne de commande "C:\Program Files\CollabNet Subversion Server\svnserve.exe" --service -r "C:\my repositories".

Donc en résumé

  • espace après chaque paramètre sc: binpath=_, displayname=_etdepend=_
  • chaque paramètre sc contenant des espaces doit être placé entre guillemets
  • tous les guillemets supplémentaires à l'intérieur du binpath sont échappés avec des barres obliques inverses: \"
  • tous les backslashes dans le binpath ne sont pas échappés
HugoRune
la source
7
J'ai trouvé qu'il était important de s'assurer qu'il y avait un espace entre binPath = et la valeur "myservice.exe". ie binPath= "myservice.exe. L'interpréteur de ligne de commande doit s'y attendre et exiger que la commande devienne un jeton en utilisant l'espace comme délimiteur.
mrswadge
J'ai essayé de cette façon et cela a fonctionné. SC.EXE "\\ ServerName" Create "ServiceName" BinPath = "SampleService.exe"
Sai
5

J'ai eu des problèmes pour que cela fonctionne sur Windows 7. Il semblait ignorer le premier argument que j'ai transmis, alors j'ai utilisé binPath= "C:\path\to\service.exe -bogusarg -realarg1 -realarg2"et cela a fonctionné.

Craig Carpenter
la source
4

J'utilise pour simplement le créer sans paramètres, puis modifier le registre HKLM\System\CurrentControlSet\Services\[YourService].

Tony
la source
2

Cette commande fonctionne:

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

Il est également important de prendre en compte la manière dont vous accédez aux arguments dans le code de l'application.

Dans mon application c #, j'ai utilisé la classe ServiceBase:

 class MyService : ServiceBase
{

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

J'ai enregistré mon service en utilisant

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

Mais je ne pouvais pas accéder aux arguments via la argsvariable lorsque je l'exécutais en tant que service.

La documentation MSDN suggère de ne pas utiliser la méthode Main pour récupérer les arguments binPathou ImagePath. Au lieu de cela, il suggère de placer votre logique dans la OnStartméthode, puis d'utiliser (C #) Environment.GetCommandLineArgs();.

Pour accéder aux premiers arguments, arg1je dois faire comme ceci:

class MyService : ServiceBase
 {

    protected override void OnStart(string[] args)
    {

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

       }
 }

cela imprimerait

       arg1 == arg1
Panciz
la source
Vous pouvez également obtenir vos arg1 et arg2 à partir du paramètre args sur la méthode Main.
Wojciech Mikołajewicz
1

J'ai trouvé un moyen d'utiliser sc.

sc config binPath = "\" c: \ chemin avec des espaces \ service_executable.exe \ ""

En d'autres termes, utilisez \ pour échapper à tous les "s que vous voulez survivre au transit dans le registre.

Rem Onyshczak
la source
1

Un exemple de création de service d'utilisation de barres obliques inverses avec de nombreux guillemets.

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
la source
0

Assurez-vous d'avoir des guillemets au début et à la fin de votre valeur binPath.

cripox
la source
1
Étant donné un chemin "c: \ abc \ def.exe", j'ai essayé de passer Param1 = "ghi" comme ceci: binPath = "c: \ abc \ def.exe / Param1 = ghi". Mais pas de travail ...
greg sympatrique
0

Je ne pouvais pas gérer le problème avec vos propositions, à la fin avec le dossier x86, cela ne fonctionnait que dans Power Shell (Windows Server 2012) en utilisant des variables d'environnement:

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

Si vous avez essayé tout ce qui précède et que vous ne pouvez toujours pas passer d'arguments à votre service, si votre service a été écrit en C / C ++, voici ce qui pourrait être le problème: lorsque vous démarrez votre service via "sc start arg1 arg2 ..." , SC appelle la fonction ServiceMain de votre service directement avec ces arguments. Mais lorsque Windows démarre votre service (au démarrage, par exemple), c'est la fonction principale de votre service (_tmain) qui est appelée, avec les paramètres du "binPath" du registre.

BlueRiver
la source
0

cela ne fonctionne pas dans le Powershell et devrait utiliser CMD dans mon cas

William
la source
corrigé dans PowerShell 5.1
oetzi