| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- //go:build windows
- // +build windows
- package servicehost
- import (
- log "github.com/sirupsen/logrus"
- "fmt"
- "golang.org/x/sys/windows/svc"
- "golang.org/x/sys/windows/svc/debug"
- "os"
- "path"
- "path/filepath"
- "time"
- )
- type otWindowsService struct{}
- //gocyclo:ignore
- func (m *otWindowsService) Execute(args []string, r <-chan svc.ChangeRequest, status chan<- svc.Status) (svcSpecificExitCode bool, exitCode uint32) {
- const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue
- tick := time.Tick(1 * time.Minute)
- status <- svc.Status{State: svc.StartPending}
- status <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
- log.Info("Servicehost started")
- for {
- select {
- case <-tick:
- log.Debug("servicehost Tick")
- case c := <-r:
- switch c.Cmd {
- case svc.Interrogate:
- status <- c.CurrentStatus
- case svc.Stop, svc.Shutdown:
- log.Info("Stopping service")
- return false, 0
- case svc.Pause:
- status <- svc.Status{State: svc.Paused, Accepts: cmdsAccepted}
- case svc.Continue:
- status <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
- default:
- log.Infof("Unexpected control request: %d", c.Cmd)
- }
- }
- }
- }
- func setupLogging() {
- logsDir := path.Join(GetConfigFilePath(), "logs")
- os.MkdirAll(logsDir, 0755)
- timestamp := time.Now().Format("2006-01-02_15-04-05")
- filename := path.Join(logsDir, fmt.Sprintf("OliveTin-service-%v.log", timestamp))
- log.Infof("Setting up logging to file: %v", filename)
- f, err := os.Create(filename)
- if err != nil {
- log.Infof("Failed to open log file: %v", err)
- } else {
- log.Infof("Switching to log file: %v", f.Name())
- log.SetOutput(f)
- log.Infof("Opened log file: %v", f.Name())
- }
- }
- func GetConfigFilePath() string {
- programDataDir := path.Join(os.Getenv("ProgramData"), "OliveTin")
- _, err := os.Stat(programDataDir)
- if os.IsNotExist(err) {
- os.MkdirAll(programDataDir, 0755)
- }
- return programDataDir
- }
- func cdToExecutableDir() {
- ex, err := os.Executable()
- if err != nil {
- panic(fmt.Sprintf("Failed to get executable path: %s", err))
- }
- exPath := filepath.Dir(ex)
- err = os.Chdir(exPath)
- if err != nil {
- panic(fmt.Sprintf("Failed to change directory to executable path: %s", err))
- }
- }
- //gocyclo:ignore
- func startServiceHandler(mode string) {
- cdToExecutableDir()
- const serviceName = "OliveTin"
- var err error
- switch mode {
- case "winsvc-debug":
- log.Infof("Running Windows service in debug mode")
- err = debug.Run(serviceName, &otWindowsService{})
- case "winsvc-standard":
- log.Infof("Running Windows service in standard mode")
- err = svc.Run(serviceName, &otWindowsService{})
- case "":
- return
- default:
- log.Fatalf("Unknown servicehost service mode: %s", mode)
- }
- if err != nil {
- log.Fatalf("Failed to run service: %v", err)
- }
- log.Infof("Servicehost handler completed")
- os.Exit(0)
- }
- func Start(mode string) {
- setupLogging()
- go startServiceHandler(mode)
- }
|