使用sc.exe创建服务时如何传递上下文参数?


143

使用以下方法创建Windows服务时:

sc create ServiceName binPath= "the path"

如何将参数传递给Installer类的Context.Parameters集合?

我对sc.exe文档的阅读是,此类参数只能在的末尾传递binPath,但是我没有找到示例或能够成功做到这一点。


略过注册表中的Services键,表明ImagePath值中包含任何所需的参数,因此您binPath= "c:\abc\def.exe /Param1=ghi"的想法似乎正确。是否需要转义反斜杠(即“ c:\\ abc \\ ...”)?最糟糕的是,如果SC.EXE无法执行此操作,则可以直接编辑注册表值。
ewall

1
我放弃了sc.exe,并像这样使用installutil.exe:Installutil.exe / ServiceName =“ TheName” / targetdir =“ C:\ TheInstallDirectory \” / PackageRoot =“ PackageRootPath”
sympatric greg 2010年

我使用Installutil.exe,对于较旧的技术,我使用Windows XP / 2003 Resource Ket中的Instsrv.exe。
加里·金德尔

Answers:


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

诀窍是在您的create语句中,在=后面保留一个空格,并对包含特殊字符或空格的任何内容使用“”。

建议为服务指定一个显示名称,并将开始设置设置为自动,以使其自动启动。您可以通过在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

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


39
请记住,binPath后空间=( binPath= "C:\..."必须到场,否则这将无法工作。
洋葱骑士

1
start= auto是一项重要的操作,因此重启后该服务将自动启动。如果最终用户不是专家,则非常好
LaBracca 2014年

21
另外,如果您需要在binPath需要引号的参数中传递额外的参数,则必须对它们进行转义(\")示例:如果路径c:\some long path\some.exe "first argument"必须为binPath= "\"c:\some long path\some.exe\" \"first argument\""
Lankymart

1
如果您的args中的“ =”后面没有空格(例如binPath= ...DisplayName= ...;在我的情况下,我在DisplayName之后忘记了“ =”),那么控制台将打印该create命令的用法说明;像:DESCRIPTION: Creates a service entry... USAGE: sc <server> create....
红豌豆

3
“ =“之后的空格非常重要
ErisoHV '18

152

用于创建的服务的参数存在一些特殊的格式问题,尤其是在命令包含空格或引号的情况下:

如果要输入服务的命令行参数,则必须将整个命令行用引号引起来。(并总是binPath=在第一个引号之前和之后留一个空格,正如mrswadge指出的那样)

因此,要为命令创建服务,PATH\COMMAND.EXE --param1=xyz 请使用以下binPath参数:

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

如果可执行文件的路径包含空格,则必须将路径用引号引起来。

因此,对于同时具有参数带空格的路径的命令,您需要嵌套的引号。您必须使用反斜杠转义内部引号\"。如果参数本身包含引号,则同样适用,您也需要将其转义。

尽管使用反斜杠作为转义字符,但不必转义路径中包含的常规反斜杠。这与通常使用反斜杠作为转义符的方式相反。

所以对于这样的命令
"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中的所有反斜杠都不能转义

7
我发现确保binPath =和值“ myservice.exe”之间存在空格很重要。即binPath= "myservice.exe。命令行解释器必须对此有所期待,并要求通过使用空格作为定界符来使命令标记化。
mrswadge

我尝试过这种方法,它确实有效。SC.EXE “\\服务器”创建“服务名称” 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

2

考虑如何在应用程序代码中访问参数也很重要。

在我的C#应用​​程序中,我使用了ServiceBase类:

 class MyService : ServiceBase
{

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

我使用以下方式注册了服务

sc创建myService binpath =“ MeyService.exe arg1 arg2”

但是args当我将其作为服务运行时,无法通过变量访问参数。

MSDN文档建议不要使用Main方法来检索binPathor ImagePath参数。相反,它建议将逻辑放入OnStart方法中,然后使用(C#)Environment.GetCommandLineArgs();

要访问第一个参数,arg1我需要这样做:

class MyService : ServiceBase
 {

    protected override void OnStart(string[] args)
    {

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

       }
 }

这将打印

       arg1 == arg1

您也可以从Main方法的args参数中获取arg1和arg2。
WojciechMikołajewicz,19年

1

我找到了一种使用sc的方法。

sc config binPath =“ \” c:\ path,其中带有空格\ 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“。但没有工作...
sympatric greg 2010年

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}

0

如果您尝试了上述所有操作,但仍无法将args传递给服务,则如果您的服务是用C / C ++编写的,则可能是问题所在:通过“ sc start arg1 arg2 ...”启动服务时,SC会直接通过这些arg调用您服务的ServiceMain函数。但是,当Windows启动服务时(例如,在启动时),将调用服务的主要功能(_tmain),并带有注册表“ binPath”中的参数。


0

它在Powershell中不起作用,在我的情况下应该使用CMD


在PowerShell 5.1中修复
oetzi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.