将应用包装为 Windows 服务自启动

之前开发的wsp在 Windows 总是要通过命令行来启动,使用颇有些不方便,于是研究了下如何将其打包封装为 Windows 服务这样就可以用开机自启的方式愉快的使用了,这里介绍下相关的操作。

封装方式

目前封装应用为服务如下几种方式

  • PowerShell
  • sc.exe
  • winsw
  • nssm

前两种无需额外安装程序,但是某些应用程序可能无法兼容使用,后两者需要额外安装程序,但可以兼容绝大部分应用,下面就来一起看看。

PowerShell

PowerShell 创建服务用到的指令为 New-Service 具体可以产考官方文档。命令详情如下

1
2
3
4
5
6
7
8
9
10
11
12
New-Service
[-Name] <String>
[-BinaryPathName] <String>
[-DisplayName <String>]
[-Description <String>]
[-SecurityDescriptorSddl <String>]
[-StartupType <ServiceStartupType>]
[-Credential <PSCredential>]
[-DependsOn <String[]>]
[-WhatIf]
[-Confirm]
[<CommonParameters>]

以本人的 wsp 应用来举例的话,类似如下,注意 PowerShell 需要以管理员身份启动才能使用

1
New-Service -Name 'TestService' -BinaryPathName 'D:\app\wsp\wspc.exe'

这时打开任务管理器服务Tab就可以找到刚刚添加的服务了,但遗憾的是这种方式对 go 写的程序不支持,启动时会报如下错误

1
错误1053:服务没有及时响应启动或控制请求

此路不通,那么就只能原路返回,根据文档输入如下指令

1
Remove-Service -Name "TestService"

这样便可以移除刚刚添加的服务,某些版本的 PowerShell 可能不支持这个指令,可以参考后面的 sc.exe 删除服务。

sc.exe

与 PowerShell 类似是 Windows 原生的方式,根据官方文档可以得知其命令如下

1
sc.exe [<servername>] create [<servicename>] [type= {own | share | kernel | filesys | rec | interact type= {own | share}}] [start= {boot | system | auto | demand | disabled | delayed-auto}] [error= {normal | severe | critical | ignore}] [binpath= <binarypathname>] [group= <loadordergroup>] [tag= {yes | no}] [depend= <dependencies>] [obj= {<accountname> | <objectname>}] [displayname= <displayname>] [password= <password>]

套用在 wsp 上例子如下

1
sc create NewService binpath=D:\app\wsp\wspc.bat

通用的需要 cmd 以管理员身份启动,添加之后可以在服务中找到对应的服务,遗憾的是,这种方式也不行,只能再移除掉

1
sc delete NewService

winsw

前面提到winsw需要下载第三方应用在兼容性上比 Windows 自带的服务添加工具要好用的多,用这个我是成功的,下面看看相关的使用说明。

winsw官方说明中提到,winsw 支持两种创建服务的方式

  • 全局方式,用于独立管理多个启动服务管理
  • 捆绑方式,对个人开发的程序比较方便,可以内置在安装过程中中创建服务

一开始用的捆绑的方式,后面重装系统之后要重建多个自启动服务,便觉得麻烦于是转而用了全局模式,结果折腾了半天一直提示

1
winsw unable to locate winsw.[xml|yml] file within executable directory

找了半天资料发现网上的要么都是用的捆绑模式,要么全局模式也没成功,更有的直接说全局模式是失效的,把握看的是一愣一愣的。

后面仔细看了下winsw官方说明发现,在开头写道

We are actively developing WinSW 3. Please refer to the v2 branch for previous version documentation.

我看了看旁边的 Release Latest 版本是 2.x 的版本,而当前的文档中的全局模式的是 3.x 版本的特性,也就是说需要点进 Release 下载仍在 alpha 的 3.x 版本才能用全局模式

这里选择下载最小的 WinSW-net461.exe 做为全局模式管理的工具,接着便是配置要注册的应用了,参考官方配置文档以 wsp为例,创建 wspc.xml 文件

1
2
3
4
5
6
7
8
<service>
<id>wspc</id>
<name>wspc</name>
<env name="HOME" value="D:\app\wsp"/>
<executable>%HOME%\wspc.exe</executable>
<arguments>-c "%HOME%\wspc.json"</arguments>
<log mode="roll"></log>
</service>

重命名 WinSW-net461.exewinsw.exe 使用命令 winsw install wspc.xml 即可创建 wspc 服务

如下是 winsw 一些命令

Command Description
install Installs the service.
uninstall Uninstalls the service.
start Starts the service.
stop Stops the service.
restart Stops and then starts the service.
status Checks the status of the service.
refresh Refreshes the service properties without reinstallation.

捆绑模式相对简单简单,将 WinSW-net461.exe 重命名为 wspc.exe,保持与 wspc.xml 同一目录下,然后使用 wspc install 即可创建服务。

写在最后

至于 nssm 也有部分人用,不过由于其很久没更新加上winsw已经满足了我的要求,就没有再做相关的学习了,最后拿着 3.x 的文档用着 2.x 的程序这种错误希望自己以后不要再犯了,笑哭。