将 Go 程序注册为一个 Window 服务(原生)

Thu 22 April 2021

写了一个小玩具需要一直放在后台运行,就用 Windows Service 吧! Service 可以在后台长时间运行程序,并且可以在开机时启动、随时暂停和恢复,非常适合跑一些不需要管理的任务。官方提供了 sys/windows/svc 包对 Service 提供了必要的支持,虽然用起来比较繁琐,但是学习可以较深的理解 Windows 处理 Service 的一些细节。那本文就来用 sys/windows/svc 和其子包实现了一个提供 http 服务的小 demo,可以通过 shell 去注册和控制 Service,我们可以随时运行 services.msc 打开服务窗口,方便调试

注册一个 Service 先启动一个 http 服务,解析一下命令行,使用 --install 的时候去注册 Service。为表简洁,下面的代码就不贴 httpService 函数和一些解析的代码了

package main

import ( "flag" "net/http" ) var flagServiceInstall = flag.Bool("install", false, "Install service")

func main() { flag.Parse() if *flagServiceInstall { ... install service } httpService() }

func httpService() { http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { writer.Write([]byte("

Hello world

")) })

_ = http.ListenAndServe("0.0.0.0:8080", nil)

} 接下来我们写一个方法去注册服务。首先使用 mgr 包去建立到服务控制管理器的连接,成功后就可以使用 CreateService 函数建立新的 Service 了。CreateService 需要的 mgr.Config 并不是每一个配置项都是必须的,有一些可选值可以参考我找到的微软的官方文档: ServiceType 枚举 (System.ServiceProcess) | Microsoft Docs ServiceStartMode 枚举 (System.ServiceProcess) | Microsoft Docs

func install() { m, err := mgr.Connect() if err != nil { log.Fatalln(err) } defer m.Disconnect()

s, err := m.CreateService("Service name", "program path",
    mgr.Config{
        ServiceType:      windows.SERVICE_WIN32_OWN_PROCESS,
        StartType:        windows.SERVICE_AUTO_START,
        ServiceStartName: "Service name",
        DisplayName:      "Service alias name",
        Description:      "Service Description",
        DelayedAutoStart: false,
    },
    "-t -r ....",
)
if err != nil {
    log.Fatalln(err)
}
s.Close()

}

Category: 编程go