Ao criar um serviço com sc.exe, como passar parâmetros de contexto?

143

Ao criar o serviço do Windows usando:

sc create ServiceName binPath= "the path"

como os argumentos podem ser passados ​​para a coleção Context.Parameters da classe Installer?

Minha leitura da sc.exedocumentação é que esses argumentos só poderiam ser passados ​​no final de binPath, mas não encontrei um exemplo ou consegui fazer isso com êxito.

greg simpático
fonte
Uma olhada na chave Serviços no Registro sugere que todos os parâmetros necessários estão incluídos no valor do ImagePath; portanto, essa é binPath= "c:\abc\def.exe /Param1=ghi"a idéia certa. As barras invertidas precisam ser escapadas (ou seja, "c: \\ abc \\ ...")? Pior, você pode editar diretamente o valor do Registro posteriormente, se o SC.EXE não puder fazer isso.
eWall
1
Eu desisti de sc.exe e estou usando installutil.exe assim: InstallUtil / ServiceName =”varNome” / targetdir =”C: \ TheInstallDirectory \” / PackageRoot =”PackageRootPath”
sympatric greg
Usei o Installutil.exe e, para tecnologias mais antigas, uso o Instsrv.exe do Windows XP / 2003 Resource Ket.
Gary Kindel

Respostas:

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

O truque é deixar um espaço após o = na instrução de criação e também usar "" para qualquer coisa que contenha caracteres ou espaços especiais.

É aconselhável especificar um Nome de exibição para o serviço, além de definir a configuração inicial como automática, para que inicie automaticamente. Você pode fazer isso especificando DisplayName= yourdisplaynamee start= autoem sua instrução create.

Aqui está um exemplo:

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

Se isso funcionou, você deverá ver:

[SC] CreateService SUCCESS

ATUALIZAÇÃO 1

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

Mhmd
fonte
39
Lembre-se de que o espaço após binPath = ( binPath= "C:\...") precisa estar presente ou isso não funcionará.
Cebola-Knight
1
start= autoé importante, portanto, após a reinicialização, o serviço será iniciado automaticamente. Muito bom no caso do usuário final não é um especialista
LaBracca
21
Além disso, se você precisa passar parâmetros extras na binPathque exigem aspas têm de ser escapado ( \") exemplo: se o caminho era c:\some long path\some.exe "first argument"que teria de serbinPath= "\"c:\some long path\some.exe\" \"first argument\""
Lankymart
1
Se você não tiver um espaço após o "=" em seus argumentos (como binPath= ...e DisplayName= ...; no meu caso, esqueci o "=" após DisplayName), o console imprimirá as instruções de uso do createcomando; como: DESCRIPTION: Creates a service entry... USAGE: sc <server> create....etc
The Red Pea
3
Os espaços após o "=" são muito importantes
ErisoHV 06/04
152

Os parâmetros para serviços criados têm alguns problemas de formatação peculiares, principalmente se o comando incluir espaços ou aspas:

Se você deseja inserir parâmetros de linha de comando para o serviço, é necessário colocar a linha de comando inteira entre aspas. (E sempre deixe um espaço binPath=antes e depois da primeira cotação, como mrswadge apontou)

Portanto, para criar um serviço para o comando, PATH\COMMAND.EXE --param1=xyz você usaria o seguinte parâmetro binPath:

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

Se o caminho para o executável contiver espaços , você deverá colocar o caminho entre aspas.

Assim, por um comando que tem ambos os parâmetros e um caminho com espaços, você precisa de aspas aninhadas . Você precisa escapar das aspas internas com barras invertidas\" . O mesmo vale se os próprios parâmetros contiverem aspas, você precisará escapar delas também.

Apesar de usar barras invertidas como caracteres de escape, você não precisa escapar das barras invertidas regulares contidas no caminho. Isso é contrário ao modo como você normalmente usa barras invertidas como caracteres de escape.

Portanto, para um 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

Aqui está um exemplo concreto da documentação do SVNserve, que mostra todos os casos especiais:

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

(quebras de linha são adicionadas para facilitar a leitura, não as inclua)

Isso adicionaria um novo serviço com a linha de comando "C:\Program Files\CollabNet Subversion Server\svnserve.exe" --service -r "C:\my repositories".

Então, em resumo

  • espaço após cada parâmetro sc: binpath=_ , displayname=_edepend=_
  • cada parâmetro sc que contém espaços deve ser colocado entre aspas
  • todas as aspas adicionais dentro do caminho do bin são escapadas com barras invertidas: \"
  • todas as barras invertidas dentro do caminho de bin não são escapadas
HugoRune
fonte
7
Achei importante garantir que haja um espaço entre binPath = e o valor "myservice.exe". ie binPath= "myservice.exe. O intérprete da linha de comando deve estar esperando isso e exigindo que o comando seja tokenizado usando espaço como delimitador.
mrswadge
Eu tentei dessa maneira e funcionou. SC.EXE "\\ ServerName" Criar "ServiceName" BinPath = "SampleService.exe"
Sai
5

Eu tive problemas para fazer isso funcionar no Windows 7. Pareceu ignorar o primeiro argumento que eu passei, então usei binPath= "C:\path\to\service.exe -bogusarg -realarg1 -realarg2"e funcionou.

Craig Carpenter
fonte
4

Eu uso apenas para criá-lo sem parâmetros e, em seguida, edito o registro HKLM\System\CurrentControlSet\Services\[YourService].

Tony
fonte
2

Este comando funciona:

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

Também é importante levar em consideração como você acessa os argumentos no código do aplicativo.

No meu aplicativo c #, usei a classe ServiceBase:

 class MyService : ServiceBase
{

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

Registrei meu serviço usando

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

Mas não consegui acessar os argumentos através da argsvariável quando a executo como um serviço.

A documentação do MSDN sugere não usar o método Main para recuperar os argumentos binPathou ImagePath. Em vez disso, sugere colocar sua lógica no OnStartmétodo e usar (C #) Environment.GetCommandLineArgs();.

Para acessar os primeiros argumentos arg1, preciso fazer o seguinte:

class MyService : ServiceBase
 {

    protected override void OnStart(string[] args)
    {

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

       }
 }

isso imprimiria

       arg1 == arg1
Panciz
fonte
Você também pode obter seu arg1 e arg2 do parâmetro args no método Main.
Wojciech Mikołajewicz 14/03/19
1

Eu encontrei uma maneira de usar sc.

sc config binPath = "\" c: \ caminho com espaços nele \ service_executable.exe \ ""

Em outras palavras, use \ para escapar dos "" que você deseja sobreviver ao trânsito para o registro.

Rem Onyshczak
fonte
1

Um exemplo de criação de serviço do uso de barras invertidas com muitas aspas duplas.

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
fonte
0

Certifique-se de ter aspas no início e no final do seu valor binPath.

cripox
fonte
1
Dado o caminho "c: \ abc \ def.exe", tentei passar Param1 = "ghi" assim: binPath = "c: \ abc \ def.exe / Param1 = ghi". Mas não trabalhoso ...
greg
0

Não consegui lidar com o problema com suas propostas; no final, com a pasta x86, ela só funcionava no power shell (windows server 2012) usando variáveis ​​de ambiente:

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

Se você tentou todas as opções acima e ainda não consegue passar argumentos para o seu serviço, se o serviço foi escrito em C / C ++, eis o que poderia ser o problema: quando você inicia o serviço através de "sc start arg1 arg2 ..." , SC chama a função ServiceMain do seu serviço diretamente com esses argumentos. Mas quando o Windows inicia o serviço (no momento da inicialização, por exemplo), é chamada a principal função do serviço (_tmain), com parâmetros do "binPath" do registro.

BlueRiver
fonte
0

não está funcionando no Powershell e deve usar o CMD no meu caso

William
fonte
corrigido no PowerShell 5.1
oetzi 28/04