我该如何配置用Go编写的Windows服务的故障操作?

5
我正在使用golang.org/x/sys/windows/svc包编写Go语言的Windows服务。
到目前为止,一切都很顺利,非常容易入手,我很喜欢它。
我已经编写了一些自动更新功能,并希望服务在完成更新后重新启动自己。
我尝试使用SCM生成一个重新启动服务的进程,但是它记录了一个错误消息,似乎与尝试在Local System下控制服务有关。
The service process could not connect to the service controller. 

更好/更简单的方法似乎是使用os.Exit(1),并将服务的故障操作设置为失败时重启,这个方法非常有效!但唯一的问题是,在Go中没有功能可以以编程方式配置这些选项。
我做了一些调查,看起来它们是通过在advapi32.dll中传递一个结构体给ChangeServiceConfig2来配置的-参见如何创建在崩溃时重新启动的服务
golang/sys/blob/master/windows/svc/mgr/config.go中的func updateDescription(handle windows.Handle, desc string) error函数中,代码已经调用了windows.ChangeServiceConfig2,这是一个链接到DLL调用的链接。
而且,SERVICE_FAILURE_ACTIONS结构的Microsoft文档在这里
我很难弄清楚如何使用Go构建和传递该结构体-有人有什么见解吗?
1个回答

3

在参考了这里的指导以及阅读现有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秒后重置故障计数器。

我刚刚测试了一下,似乎可以正常工作。


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