1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build windows
6// +build windows
7
8package main
9
10import (
11	"fmt"
12	"os"
13	"path/filepath"
14
15	"golang.org/x/sys/windows/svc/eventlog"
16	"golang.org/x/sys/windows/svc/mgr"
17)
18
19func exePath() (string, error) {
20	prog := os.Args[0]
21	p, err := filepath.Abs(prog)
22	if err != nil {
23		return "", err
24	}
25	fi, err := os.Stat(p)
26	if err == nil {
27		if !fi.Mode().IsDir() {
28			return p, nil
29		}
30		err = fmt.Errorf("%s is directory", p)
31	}
32	if filepath.Ext(p) == "" {
33		p += ".exe"
34		fi, err := os.Stat(p)
35		if err == nil {
36			if !fi.Mode().IsDir() {
37				return p, nil
38			}
39			err = fmt.Errorf("%s is directory", p)
40		}
41	}
42	return "", err
43}
44
45func installService(name, desc string) error {
46	exepath, err := exePath()
47	if err != nil {
48		return err
49	}
50	m, err := mgr.Connect()
51	if err != nil {
52		return err
53	}
54	defer m.Disconnect()
55	s, err := m.OpenService(name)
56	if err == nil {
57		s.Close()
58		return fmt.Errorf("service %s already exists", name)
59	}
60	s, err = m.CreateService(name, exepath, mgr.Config{DisplayName: desc}, "is", "auto-started")
61	if err != nil {
62		return err
63	}
64	defer s.Close()
65	err = eventlog.InstallAsEventCreate(name, eventlog.Error|eventlog.Warning|eventlog.Info)
66	if err != nil {
67		s.Delete()
68		return fmt.Errorf("SetupEventLogSource() failed: %s", err)
69	}
70	return nil
71}
72
73func removeService(name string) error {
74	m, err := mgr.Connect()
75	if err != nil {
76		return err
77	}
78	defer m.Disconnect()
79	s, err := m.OpenService(name)
80	if err != nil {
81		return fmt.Errorf("service %s is not installed", name)
82	}
83	defer s.Close()
84	err = s.Delete()
85	if err != nil {
86		return err
87	}
88	err = eventlog.Remove(name)
89	if err != nil {
90		return fmt.Errorf("RemoveEventLogSource() failed: %s", err)
91	}
92	return nil
93}
94