我使用golang.org/x/sys/windows/svc
包在Go中编写Windows服务。
到目前为止,这一切都很好,很容易开始,我喜欢它。
我写了一些自动更新function,我想要服务在完成更新时自行重启。
我已经尝试过产生一个使用SCM
重新启动服务的进程,但是它logging了一个错误消息,这似乎是在以本地系统的身份运行时试图控制服务。
The service process could not connect to the service controller.
一个更好/更简单的方法似乎是os.Exit(1)
并有服务Failure Actions
设置为Restart on Failure
,这工作出色!
唯一的问题是,似乎没有function来使用Go以编程方式configuration这些选项。
我已经做了一些挖掘,它看起来像他们通过将一个结构传递给advapi32.dll
ChangeServiceConfig2
– 如何创build在崩溃时重新启动的服务
在golang / sys / blob / master / windows / svc / mgr / config.go – func updateDescription(handle windows.Handle, desc string) error
代码已经调用了windows.ChangeServiceConfig2
,它是DLL调用的链接。
并且这个SERVICE_FAILURE_ACTIONS
结构的微软文档在这里 。
我无法弄清楚如何使用Go来构build和传递结构 – 有没有人有任何见解?
在从这里得到一些指导之后,再加上通过现有Go Windows Service界面的源代码阅读,我想出了自己的答案,我将在下面进行介绍。
对于使用Windows DLL的类型参考,MSDN文档在这里 。
我的代码如下所示:
import ( "unsafe" "golang.org/x/sys/windows" ) const ( SC_ACTION_NONE = 0 SC_ACTION_RESTART = 1 SC_ACTION_REBOOT = 2 SC_ACTION_RUN_COMMAND = 3 SERVICE_CONFIG_FAILURE_ACTIONS = 2 ) type SERVICE_FAILURE_ACTIONS struct { ResetPeriod uint32 RebootMsg *uint16 Command *uint16 ActionsCount uint32 Actions uintptr } type SC_ACTION struct { Type uint32 Delay uint32 } func setServiceFailureActions(handle windows.Handle) error { t := []SC_ACTION{ { Type: SC_ACTION_RESTART, Delay: uint32(1000) }, { Type: SC_ACTION_RESTART, Delay: uint32(10000) }, { Type: SC_ACTION_RESTART, Delay: uint32(60000) }, } m := SERVICE_FAILURE_ACTIONS{ ResetPeriod: uint32(60), ActionsCount: uint32(3), Actions: uintptr(unsafe.Pointer(&t[0])) } return windows.ChangeServiceConfig2(handle, SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&m))) }
在我的基本示例中,您需要传递一个服务句柄,然后将失败操作设置为一个硬编码的默认值:
我刚刚测试,似乎工作正常。