我正在使用该golang.org/x/sys/windows/svc软件包在Go中编写Windows服务。
golang.org/x/sys/windows/svc
到目前为止,一切都很顺利,而且很容易上手,我喜欢它。
我已经编写了一些自动更新功能,并且希望该服务在完成更新后重新启动。
我尝试生成一个进程,该进程将使用来重新启动服务SCM,但它会记录一条错误消息,该消息似乎与尝试在作为本地系统运行时尝试控制该服务有关。
SCM
The service process could not connect to the service controller.
更好的方法是,将os.Exit(1)服务Failure Actions设置为Restart on Failure,效果很好!
os.Exit(1)
Failure Actions
Restart on Failure
唯一的麻烦是,似乎没有使用Go编程配置这些选项的功能。
我已经做了一些挖掘,看起来它们是通过将结构传递给ChangeServiceConfig2in 来配置的advapi32.dll-如何创建在崩溃时重启的服务
ChangeServiceConfig2
advapi32.dll
在 golang / sys / blob / master / windows / svc / mgr / config.go中 -func updateDescription(handle windows.Handle, desc string) error
func updateDescription(handle windows.Handle, desc string) error
该代码已经调用windows.ChangeServiceConfig2,它是DLL调用的链接。
windows.ChangeServiceConfig2
SERVICE_FAILURE_ACTIONS结构的Microsoft文档在这里。
SERVICE_FAILURE_ACTIONS
我在弄清楚如何使用Go构建和传递该结构时遇到了麻烦-是否有人有任何见解?
在从这里获得一些指导之后,再通读现有Go WindowsService界面的源代码,我提出了自己的答案,我将在下面尝试记录。
对于类型参考使用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))) }
在我的基本示例中,您需要传递服务句柄,然后将失败操作设置为硬编码默认值:
我刚刚测试过,看来工作正常。