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

183

使用以下方式创建Windows服务:

sc create ServiceName binPath= "the path"

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

根据我对sc.exe文档的理解,这些参数只能通过binPath的末尾传递,但我没有找到示例或成功执行此操作。


快速浏览注册表中的“服务”键,可以发现任何必要的参数都包含在ImagePath值中,因此您的 binPath= "c:\abc\def.exe /Param1=ghi" 看起来是正确的想法。反斜杠需要转义吗(即 "c:\abc\...")?最坏的情况下,如果SC.EXE无法完成操作,您可以直接编辑注册表值。 - ewall
1
我放弃了 sc.exe,并改用 installutil.exe,命令如下:Installutil.exe /ServiceName=”服务名称” /targetdir=”C:\安装目录\” /PackageRoot=”包根路径” - sympatric greg
我使用了Installutil.exe,对于旧技术,我使用来自Windows XP/2003资源套件的Instsrv.exe。 - Gary Kindel
14个回答

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

诀窍是在创建语句中在=之后留一个空格,并且对于包含特殊字符或空格的内容,使用" "。

建议为服务指定显示名称,并将启动设置为自动启动,以便它能够自动启动。您可以在创建语句中通过指定DisplayName=yourdisplaynamestart=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


43
请注意,在binPath=(binPath= "C:\...")之后必须有空格,否则这将无法正常工作。 - Onion-Knight
2
"start=auto" 是一个重要的设置,这样在重新启动后服务会自动启动。非常适合那些不是专家级用户的终端用户。 - UnDiUdin
30
如果您需要在 binPath 中传递需要引号的额外参数,则必须进行转义 (\")。例如:如果路径为 c:\some long path\some.exe "first argument",则需要将其写成 binPath= "\"c:\some long path\some.exe\" \"first argument\""。请注意,该翻译保留了原文的意思,并尽可能使其更加通俗易懂。 - user692942
2
如果在参数中的“=”后面没有空格(例如binPath= ...DisplayName= ...;在我的情况下,我忘记了在DisplayName之后加上“=”),那么控制台将打印出“create”命令的用法说明; 如:DESCRIPTION: Creates a service entry... USAGE: sc <server> create....等等。 - Nate Anderson
3
"=" 后面的空格非常重要。 - ErisoHV
显示剩余4条评论

214

创建服务时的参数具有某些特殊的格式问题,特别是如果命令包含空格或引号:

如果您想为服务输入命令行参数,则必须用引号括起整个命令行。(并且始终在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内的所有反斜杠都不需要转义

9
确保在binPath=和值"myservice.exe"之间有一个空格非常重要,例如binPath= "myservice.exe"。命令行解释器需要这样做,并要求使用空格作为分隔符将命令进行标记化。 - mrswadge
我尝试了这种方法,它有效。SC.EXE "\ServerName" Create "ServiceName" BinPath="SampleService.exe" - Sai
1
这应该在MS文档中的sc.exe create上。 - Joseph
2
这个空格还有必要吗?现在没有空格也能工作。我正在使用Windows 10。 - Larry

14

6

我在Windows 7上使用时遇到了问题。它似乎忽略了我传递的第一个参数,所以我使用了binPath="C:\path\to\service.exe -bogusarg -realarg1 -realarg2",这样它就可以工作了。


4

我曾经只是不带参数地创建它,然后编辑注册表HKLM\System\CurrentControlSet\Services\[YourService]


4
使用反斜杠和多个双引号的服务创建示例。
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

4
在编写应用程序的代码时,考虑到如何访问参数也是非常重要的。
在我的C#应用程序中,我使用了ServiceBase类:
class MyService : ServiceBase
{
    protected override void OnStart(string[] args)
    {
        //
    }
}

我使用了注册我的服务。
sc create myService binpath= "MeyService.exe arg1 arg2"

但是当我将其作为服务运行时,无法通过args变量访问参数。
MSDN文档建议不要使用Main方法来检索binPathImagePath参数。相反,它建议将逻辑放在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。 - Wojciech Mikołajewicz

3
这个命令有效。
sc create startSvn binPath= "\"C:\Subversion\bin\svnserve.exe\" --service -r \"C:\SVN_Repository\"" displayname= "MyServer" depend= tcpip start= auto

1
我找到了一种使用sc的方法。
使用以下命令:sc config binPath= "\"c:\path with spaces in it\service_executable.exe\" "
换句话说,使用反斜杠来转义任何你想要在传输到注册表中生存的引号。

0

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


修复于PowerShell 5.1版本。 - oetzi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接