-
Notifications
You must be signed in to change notification settings - Fork 291
/
Copy pathdaemon_windows.go
117 lines (101 loc) · 3.03 KB
/
daemon_windows.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by
// license that can be found in the LICENSE file.
// Package daemon windows version
package daemon
import (
"errors"
"fmt"
"os/exec"
"syscall"
"unicode/utf16"
"unsafe"
)
var ErrWindowsUnsupported = errors.New("Adding as a service failed. Download and place nssm.exe in the path to install this service as an service. NSSM url: https://nssm.cc/")
// windowsRecord - standard record (struct) for windows version of daemon package
type windowsRecord struct {
name string
description string
dependencies []string
}
func newDaemon(name, description string, dependencies []string) (Daemon, error) {
return &windowsRecord{name, description, dependencies}, nil
}
// Install the service
func (windows *windowsRecord) Install(args ...string) (string, error) {
installAction := "Install " + windows.description + ":"
adminAccessNecessary := "Administrator access is needed to install a service."
execp, err := execPath()
if err != nil {
return installAction + failed, err
}
cmd := exec.Command("nssm.exe", "install", windows.name, execp)
out, err := cmd.Output()
if err != nil {
if len(out) > 0 {
fmt.Println(string(out))
} else {
fmt.Println("No output. Probably service already exists. Try uninstall first.")
}
return installAction + failed, err
}
if len(out) == 0 {
return adminAccessNecessary, errors.New(adminAccessNecessary)
}
return installAction + " completed.", nil
}
// Remove the service
func (windows *windowsRecord) Remove() (string, error) {
removeAction := "Removing " + windows.description + ":"
cmd := exec.Command("nssm.exe", "remove", windows.name, "confirm")
err := cmd.Run()
if err != nil {
return removeAction + failed, err
}
return removeAction + " completed.", nil
}
// Start the service
func (windows *windowsRecord) Start() (string, error) {
startAction := "Starting " + windows.description + ":"
cmd := exec.Command("nssm.exe", "start", windows.name)
err := cmd.Run()
if err != nil {
return startAction + failed, err
}
return startAction + " completed.", nil
}
// Stop the service
func (windows *windowsRecord) Stop() (string, error) {
stopAction := "Stopping " + windows.description + ":"
cmd := exec.Command("nssm.exe", "stop", windows.name)
err := cmd.Run()
if err != nil {
return stopAction + failed, err
}
return stopAction + " completed.", nil
}
// Status - Get service status
func (windows *windowsRecord) Status() (string, error) {
cmd := exec.Command("nssm.exe", "status", windows.name)
out, err := cmd.Output()
if err != nil {
return "Getting status:" + failed, err
}
return "Status: " + string(out), nil
}
// Get executable path
func execPath() (string, error) {
var n uint32
b := make([]uint16, syscall.MAX_PATH)
size := uint32(len(b))
r0, _, e1 := syscall.MustLoadDLL(
"kernel32.dll",
).MustFindProc(
"GetModuleFileNameW",
).Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size))
n = uint32(r0)
if n == 0 {
return "", e1
}
return string(utf16.Decode(b[0:n])), nil
}