Skip to content

Commit 51ab0e2

Browse files
utkarsh-extcalexbrainman
authored andcommitted
windows: add support for automatic delayed start in windows service
Change-Id: Iad33ea0f6627ac98c89dbaab0b41b3dd724c3163 GitHub-Last-Rev: 8764fdb GitHub-Pull-Request: #36 Reviewed-on: https://go-review.googlesource.com/c/sys/+/187198 Reviewed-by: Alex Brainman <[email protected]> Run-TryBot: Alex Brainman <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent cbf593c commit 51ab0e2

File tree

4 files changed

+51
-0
lines changed

4 files changed

+51
-0
lines changed

windows/service.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ type SERVICE_DESCRIPTION struct {
159159
Description *uint16
160160
}
161161

162+
type SERVICE_DELAYED_AUTO_START_INFO struct {
163+
IsDelayedAutoStartUp uint32
164+
}
165+
162166
type SERVICE_STATUS_PROCESS struct {
163167
ServiceType uint32
164168
CurrentState uint32

windows/svc/mgr/config.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type Config struct {
4343
Password string
4444
Description string
4545
SidType uint32 // one of SERVICE_SID_TYPE, the type of sid to use for the service
46+
DelayedAutoStart bool // the service is started after other auto-start services are started plus a short delay
4647
}
4748

4849
func toString(p *uint16) string {
@@ -95,6 +96,16 @@ func (s *Service) Config() (Config, error) {
9596
}
9697
p2 := (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0]))
9798

99+
b, err = s.queryServiceConfig2(windows.SERVICE_CONFIG_DELAYED_AUTO_START_INFO)
100+
if err != nil {
101+
return Config{}, err
102+
}
103+
p3 := (*windows.SERVICE_DELAYED_AUTO_START_INFO)(unsafe.Pointer(&b[0]))
104+
delayedStart := false
105+
if p3.IsDelayedAutoStartUp != 0 {
106+
delayedStart = true
107+
}
108+
98109
return Config{
99110
ServiceType: p.ServiceType,
100111
StartType: p.StartType,
@@ -106,6 +117,7 @@ func (s *Service) Config() (Config, error) {
106117
ServiceStartName: toString(p.ServiceStartName),
107118
DisplayName: toString(p.DisplayName),
108119
Description: toString(p2.Description),
120+
DelayedAutoStart: delayedStart,
109121
}, nil
110122
}
111123

@@ -119,6 +131,15 @@ func updateSidType(handle windows.Handle, sidType uint32) error {
119131
return windows.ChangeServiceConfig2(handle, windows.SERVICE_CONFIG_SERVICE_SID_INFO, (*byte)(unsafe.Pointer(&sidType)))
120132
}
121133

134+
func updateStartUp(handle windows.Handle, isDelayed bool) error {
135+
var d windows.SERVICE_DELAYED_AUTO_START_INFO
136+
if isDelayed {
137+
d.IsDelayedAutoStartUp = 1
138+
}
139+
return windows.ChangeServiceConfig2(handle,
140+
windows.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, (*byte)(unsafe.Pointer(&d)))
141+
}
142+
122143
// UpdateConfig updates service s configuration parameters.
123144
func (s *Service) UpdateConfig(c Config) error {
124145
err := windows.ChangeServiceConfig(s.Handle, c.ServiceType, c.StartType,
@@ -132,6 +153,12 @@ func (s *Service) UpdateConfig(c Config) error {
132153
if err != nil {
133154
return err
134155
}
156+
157+
err = updateStartUp(s.Handle, c.DelayedAutoStart)
158+
if err != nil {
159+
return err
160+
}
161+
135162
return updateDescription(s.Handle, c.Description)
136163
}
137164

windows/svc/mgr/mgr.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,14 @@ func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Se
149149
return nil, err
150150
}
151151
}
152+
if c.DelayedAutoStart {
153+
err = updateStartUp(h, c.DelayedAutoStart)
154+
if err != nil {
155+
windows.DeleteService(h)
156+
windows.CloseHandle(h)
157+
return nil, err
158+
}
159+
}
152160
return &Service{Name: name, Handle: h}, nil
153161
}
154162

windows/svc/mgr/mgr_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ func testConfig(t *testing.T, s *mgr.Service, should mgr.Config) mgr.Config {
8080
if err != nil {
8181
t.Fatalf("Config failed: %s", err)
8282
}
83+
if should.DelayedAutoStart != is.DelayedAutoStart {
84+
t.Fatalf("config mismatch: DelayedAutoStart is %v, but should have %v", is.DelayedAutoStart, should.DelayedAutoStart)
85+
}
8386
if should.DisplayName != is.DisplayName {
8487
t.Fatalf("config mismatch: DisplayName is %q, but should have %q", is.DisplayName, should.DisplayName)
8588
}
@@ -257,6 +260,15 @@ func TestMyService(t *testing.T) {
257260

258261
testConfig(t, s, c)
259262

263+
c.StartType = mgr.StartAutomatic
264+
c.DelayedAutoStart = true
265+
err = s.UpdateConfig(c)
266+
if err != nil {
267+
t.Fatalf("UpdateConfig failed: %v", err)
268+
}
269+
270+
testConfig(t, s, c)
271+
260272
svcnames, err := m.ListServices()
261273
if err != nil {
262274
t.Fatalf("ListServices failed: %v", err)

0 commit comments

Comments
 (0)