Skip to content

Commit 35a051a

Browse files
author
Swapnil
committed
callback support for events
1 parent 3596dfa commit 35a051a

File tree

9 files changed

+157
-15
lines changed

9 files changed

+157
-15
lines changed

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# service [![GoDoc](https://godoc.org/github.com/kardianos/service?status.svg)](https://godoc.org/github.com/kardianos/service)
1+
# service [![GoDoc](https://godoc.org/github.com/fourcorelabs/service?status.svg)](https://godoc.org/github.com/fourcorelabs/service)
22

33
service will install / un-install, start / stop, and run a program as a service (daemon).
44
Currently supports Windows XP+, Linux/(systemd | Upstart | SysV), and OSX/Launchd.
@@ -9,6 +9,9 @@ despite the substantial differences.
99
It also can be used to detect how a program is called, from an interactive
1010
terminal or from a service manager.
1111

12+
Added Support for windows callbacks on events. This can help you receive session change and other notifications
13+
Look at examples/winextracallback for how to do this
14+
1215
## BUGS
1316
* Dependencies field is not implemented for Linux systems and Launchd.
1417
* OS X when running as a UserService Interactive will not be accurate.

example/logging/main.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import (
1010
"log"
1111
"time"
1212

13-
"github.com/kardianos/service"
13+
"github.com/fourcorelabs/service"
1414
)
1515

1616
var logger service.Logger
1717

1818
// Program structures.
19-
// Define Start and Stop methods.
19+
//
20+
// Define Start and Stop methods.
2021
type program struct {
2122
exit chan struct{}
2223
}
@@ -54,11 +55,12 @@ func (p *program) Stop(s service.Service) error {
5455
}
5556

5657
// Service setup.
57-
// Define service config.
58-
// Create the service.
59-
// Setup the logger.
60-
// Handle service controls (optional).
61-
// Run the service.
58+
//
59+
// Define service config.
60+
// Create the service.
61+
// Setup the logger.
62+
// Handle service controls (optional).
63+
// Run the service.
6264
func main() {
6365
svcFlag := flag.String("service", "", "Control the system service.")
6466
flag.Parse()

example/runner/runner.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"os/exec"
1515
"path/filepath"
1616

17-
"github.com/kardianos/service"
17+
"github.com/fourcorelabs/service"
1818
)
1919

2020
// Config is the runner app config structure.

example/simple/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ package main
88
import (
99
"log"
1010

11-
"github.com/kardianos/service"
11+
"github.com/fourcorelabs/service"
1212
)
1313

1414
var logger service.Logger

example/stopPause/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"os"
1111
"time"
1212

13-
"github.com/kardianos/service"
13+
"github.com/fourcorelabs/service"
1414
)
1515

1616
var logger service.Logger

example/winextracallback/main.go

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Copyright 2015 Daniel Theophanes.
2+
// Use of this source code is governed by a zlib-style
3+
// license that can be found in the LICENSE file.
4+
5+
// simple does nothing except block while running the service.
6+
package main
7+
8+
import (
9+
"fmt"
10+
"log"
11+
"os"
12+
"strings"
13+
"time"
14+
15+
"github.com/fourcorelabs/service"
16+
"golang.org/x/sys/windows/svc"
17+
)
18+
19+
var notifyMap = map[svc.Cmd]string{
20+
svc.Stop: "SERVICE_CONTROL_STOP",
21+
svc.Pause: "SERVICE_CONTROL_PAUSE",
22+
svc.Continue: "SERVICE_CONTROL_CONTINUE",
23+
svc.Interrogate: "SERVICE_CONTROL_INTERROGATE",
24+
svc.Shutdown: "SERVICE_CONTROL_SHUTDOWN",
25+
svc.ParamChange: "SERVICE_CONTROL_PARAMCHANGE",
26+
svc.NetBindAdd: "SERVICE_CONTROL_NETBINDADD",
27+
svc.NetBindRemove: "SERVICE_CONTROL_NETBINDREMOVE",
28+
svc.NetBindEnable: "SERVICE_CONTROL_NETBINDENABLE",
29+
svc.NetBindDisable: "SERVICE_CONTROL_NETBINDDISABLE",
30+
svc.DeviceEvent: "SERVICE_CONTROL_DEVICEEVENT",
31+
svc.HardwareProfileChange: "SERVICE_CONTROL_HARDWAREPROFILECHANGE",
32+
svc.PowerEvent: "SERVICE_CONTROL_POWEREVENT",
33+
svc.SessionChange: "SERVICE_CONTROL_SESSIONCHANGE",
34+
svc.PreShutdown: "SERVICE_CONTROL_PRESHUTDOWN",
35+
}
36+
37+
var logger service.Logger
38+
39+
type program struct{}
40+
41+
func (p *program) handleService(svc service.Service, action string) error {
42+
43+
switch action {
44+
case "status":
45+
status, err := svc.Status()
46+
if err != nil {
47+
return fmt.Errorf("cannot get status, error: %v", err)
48+
}
49+
switch status {
50+
case service.StatusRunning:
51+
fmt.Println("Status Running")
52+
case service.StatusStopped:
53+
fmt.Println("Status Stopped")
54+
default:
55+
fmt.Println("Status Unknown")
56+
}
57+
return nil
58+
default:
59+
return service.Control(svc, action)
60+
}
61+
}
62+
63+
func (p *program) Start(s service.Service) error {
64+
logger.Infof("Program started on %v platform", service.Platform())
65+
go Main()
66+
return nil
67+
}
68+
69+
func (p *program) Stop(s service.Service) error {
70+
// Stop should not block. Return with a few seconds.
71+
return nil
72+
}
73+
74+
func (p *program) Callback(e svc.ChangeRequest) {
75+
if logger == nil {
76+
return
77+
}
78+
79+
if v, ok := notifyMap[e.Cmd]; ok {
80+
logger.Infof("Received Event: %v", v)
81+
} else {
82+
logger.Infof("Received Unknown Event: %v", e.Cmd)
83+
}
84+
}
85+
86+
func main() {
87+
prg := &program{}
88+
89+
svcConfig := &service.Config{
90+
Name: "GoServiceExampleSimple",
91+
DisplayName: "Go Service Example",
92+
Description: "This is an example Go service.",
93+
Option: service.KeyValue{"ExtraCommandsAccepted": svc.AcceptSessionChange, "AcceptedCommandsCallback": prg.Callback},
94+
}
95+
96+
s, err := service.New(prg, svcConfig)
97+
if err != nil {
98+
log.Fatal(err)
99+
}
100+
101+
logger, err = s.Logger(nil)
102+
if err != nil {
103+
log.Fatal(err)
104+
}
105+
106+
if len(os.Args) <= 1 {
107+
if err := s.Run(); err != nil {
108+
logger.Error(err)
109+
}
110+
} else {
111+
if err := prg.handleService(s, strings.ToLower(os.Args[1])); err != nil {
112+
logger.Error(err)
113+
}
114+
}
115+
}
116+
117+
func Main() {
118+
for range time.NewTicker(30 * time.Second).C {
119+
logger.Info("Weirdo Service still running")
120+
}
121+
}

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module github.com/kardianos/service
1+
module github.com/fourcorelabs/service
22

33
go 1.12
44

service_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"testing"
1010
"time"
1111

12-
"github.com/kardianos/service"
12+
"github.com/fourcorelabs/service"
1313
)
1414

1515
func TestRunInterrupt(t *testing.T) {

service_windows.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,31 @@ func (ws *windowsService) Execute(args []string, r <-chan svc.ChangeRequest, cha
182182
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown
183183
changes <- svc.Status{State: svc.StartPending}
184184

185+
cmdsAcceptedUpdate := cmdsAccepted
186+
if ev, ok := ws.Option["ExtraCommandsAccepted"]; ok {
187+
if conv, ok := ev.(svc.Accepted); ok {
188+
cmdsAcceptedUpdate |= conv
189+
}
190+
}
191+
192+
var eventCallback func(svc.ChangeRequest)
193+
if f, ok := ws.Option["AcceptedCommandsCallback"]; ok {
194+
if conv, ok := f.(func(svc.ChangeRequest)); ok {
195+
eventCallback = conv
196+
}
197+
}
198+
185199
if err := ws.i.Start(ws); err != nil {
186200
ws.setError(err)
187201
return true, 1
188202
}
189-
190-
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
203+
changes <- svc.Status{State: svc.Running, Accepts: cmdsAcceptedUpdate}
191204
loop:
192205
for {
193206
c := <-r
207+
if eventCallback != nil {
208+
go eventCallback(c)
209+
}
194210
switch c.Cmd {
195211
case svc.Interrogate:
196212
changes <- c.CurrentStatus

0 commit comments

Comments
 (0)