Загрузка...

Running a Go exe as a Windows Service - Backup Files Software From Scratch Written in Go #16

In this tutorial series #16, we will learn how to use the Kardianos Service package written in pure Go to install Golang Executable as the Windows Service using Golang programming language with step by step guide. #MaharlikansCode #InstallGoExeAsWindowsService #Golang #KardianosService #LifeAsSoftwareDeveloper #Maharlikans #FilipinoSoftwareDeveloper If you go with extra mile for buying me a cup of coffee, I appreciate it guys: https://ko-fi.com/maharlikanscode Source Codes: main.go: package main import ( "flag" "fmt" "log" "os" "os/exec" "path/filepath" "runtime" "strconv" "strings" "syscall" "unsafe" "github.com/itrepablik/itrlog" "github.com/kardianos/service" "golang.org/x/sys/windows" ) // TH32CS_SNAPPROCESS is described in https://msdn.microsoft.com/de-de/library/windows/desktop/ms682489(v=vs.85).aspx const TH32CS_SNAPPROCESS = 0x00000002 // Config is the runner app config structure. type Config struct { Name, DisplayName, Description string Dir string Exec string Args []string Env []string Stderr, Stdout string } var logger service.Logger type program struct { exit chan struct{} service service.Service *Config cmd *exec.Cmd } func (p *program) Start(s service.Service) error { fullExec, err := exec.LookPath(p.Exec) if err != nil { return fmt.Errorf("Failed to find executable %q: %v", p.Exec, err) } p.cmd = exec.Command(fullExec, p.Args...) p.cmd.Dir = p.Dir p.cmd.Env = append(os.Environ(), p.Env...) go p.run() return nil } func (p *program) run() { logger.Info("Starting ", p.DisplayName) itrlog.Info("Starting ", p.DisplayName) defer func() { if service.Interactive() { p.Stop(p.service) } else { p.service.Stop() } }() if p.Stderr != "" { f, err := os.OpenFile(p.Stderr, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0777) if err != nil { logger.Warningf("Failed to open std err %q: %v", p.Stderr, err) itrlog.Warnf("Failed to open std err %q: %v", p.Stderr, err) return } defer f.Close() p.cmd.Stderr = f } if p.Stdout != "" { f, err := os.OpenFile(p.Stdout, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0777) if err != nil { logger.Warningf("Failed to open std out %q: %v", p.Stdout, err) itrlog.Warnf("Failed to open std out %q: %v", p.Stdout, err) return } defer f.Close() p.cmd.Stdout = f } err := p.cmd.Run() if err != nil { logger.Warningf("Error running: %v", err) itrlog.Warnf("Error running: %v", err) } return } func (p *program) Stop(s service.Service) error { defer close(p.exit) logger.Info("Stopping ", p.DisplayName) itrlog.Info("Stopping ", p.DisplayName) WindowsKillProcessByPID() if p.cmd.ProcessState.Exited() == false { p.cmd.Process.Kill() } if service.Interactive() { os.Exit(0) } return nil } // WindowsKillProcessByPID is the kill a current process by PID. func WindowsKillProcessByPID() { // Kill the 'gokopy.exe' process as well. procs, err := processes() if err != nil { logger.Error(err) itrlog.Error(err) } explorer := findProcessByName(procs, "gokopy.exe") if explorer != nil { kill := exec.Command("taskkill", "/T", "/F", "/PID", strconv.Itoa(explorer.ProcessID)) err := kill.Run() if err != nil { logger.Error(err) itrlog.Error(err) } } } // WindowsProcess is an implementation of Process for Windows. type WindowsProcess struct { ProcessID int ParentProcessID int Exe string } func processes() ([]WindowsProcess, error) { handle, err := windows.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) if err != nil { return nil, err } defer windows.CloseHandle(handle) var entry windows.ProcessEntry32 entry.Size = uint32(unsafe.Sizeof(entry)) // get the first process err = windows.Process32First(handle, &entry) if err != nil { return nil, err } results := make([]WindowsProcess, 0, 50) for { results = append(results, newWindowsProcess(&entry)) err = windows.Process32Next(handle, &entry) if err != nil { // windows sends ERROR_NO_MORE_FILES on last process if err == syscall.ERROR_NO_MORE_FILES { return results, nil } return nil, err } } } func findProcessByName(processes []WindowsProcess, name string) *WindowsProcess { for _, p := range processes { if strings.ToLower(p.Exe) == strings.ToLower(name) { return &p } } return nil } func newWindowsProcess(e *windows.ProcessEntry32) WindowsProcess { // Find when the string ends for decoding end := 0 for { if e.ExeFile[end] == 0 { break } end++ } return WindowsProcess{ ProcessID: int(e.ProcessID), ParentProcessID: int(e.ParentProcessID), Exe: syscall.UTF16ToString(e.ExeFile[:end]), } } func main() { // Call the kardianos OS service library here svcFlag := flag.String("service", "", "Control the system service.") flag.Parse() svcConfig := &service.Config{ Name: "gokopy", DisplayName: "gokopy", Description: "A lightweight automated backup file software.", } } Source codes omitted...

Видео Running a Go exe as a Windows Service - Backup Files Software From Scratch Written in Go #16 автора Учимся программировать на JavaScript с нуля
Страницу в закладки Мои закладки
Все заметки Новая заметка Страницу в заметки