如何configuration用Go编写的Windows服务的失败操作?

我使用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.gofunc 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))) } 

在我的基本示例中,您需要传递一个服务句柄,然后将失败操作设置为一个硬编码的默认值:

  1. 1秒后第一次重新启动。
  2. 10秒后再次重新启动。
  3. 60秒后重新开始第三次以后的任何时间。
  4. 60秒后重置故障计数器。

我刚刚测试,似乎工作正常。