win32-service 0.8.7 → 0.8.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/CHANGES +21 -0
- data/MANIFEST +3 -0
- data/README +1 -7
- data/Rakefile +3 -6
- data/appveyor.yml +48 -0
- data/certs/djberg96_pub.pem +21 -0
- data/doc/daemon.txt +2 -2
- data/doc/service.txt +2 -2
- data/examples/demo_daemon.rb +1 -0
- data/examples/demo_daemon_ctl.rb +3 -2
- data/lib/win32-daemon.rb +1 -0
- data/lib/win32-service.rb +1 -0
- data/lib/win32/daemon.rb +14 -16
- data/lib/win32/service.rb +53 -43
- data/lib/win32/windows/functions.rb +4 -4
- data/lib/win32/windows/structs.rb +1 -1
- data/test/test_win32_daemon.rb +1 -1
- data/test/test_win32_service.rb +58 -27
- data/test/test_win32_service_configure.rb +17 -6
- data/test/test_win32_service_create.rb +47 -23
- data/test/test_win32_service_info.rb +24 -23
- data/win32-service.gemspec +3 -1
- metadata +54 -7
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c9e7a6cfd6aa6f113daf315e64979fb66c9c83b
|
4
|
+
data.tar.gz: bc7920b71189a326bfd7b2b6e9affd2bd1fb1ded
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3bca8887a30ced151972c81d62d0d724ba3954b62b7ce435b02053ce91d674602a2d274955992c6b4a28d751ce574da8f2ffb6aa5045e27b0b6d0cb345fa5fe
|
7
|
+
data.tar.gz: 8ad98044dd9fdee7917a2267715d0ecbd1b37d946525fba1a340391e877a6f340464fef6c31b4ad93f70e020e126ab5f986bc4830050d1bc66c366a2d9f59bda
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
data/CHANGES
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
== 0.8.8 - 24-Jun-2016
|
2
|
+
* Fixed the function prototypes for CreateEvent and AdjustTokenPrivileges
|
3
|
+
where I was using :bool instead of :int.
|
4
|
+
* Updated the various FFI module wrapper names so that they're more distinctly
|
5
|
+
namespaced. Avoids a clash with the win32-eventlog gem, and possibly others.
|
6
|
+
* Discovered more places where QueryServiceConfig2 could fail while attempting
|
7
|
+
to get failure actions and delayed auto start info. Instead of failing,
|
8
|
+
these now set their respective data to nil.
|
9
|
+
* A timeout value in our main observer thread was increased to potentially
|
10
|
+
improve performance. Feedback welcome.
|
11
|
+
* This gem is now signed.
|
12
|
+
* Added the win32-service.rb and win32-daemon.rb files for convenience.
|
13
|
+
* Use require_relative internally.
|
14
|
+
* Added win32-security as a development dependency. It was already being used
|
15
|
+
for tests but now it's actually part of the gemspec.
|
16
|
+
* Many tests are now skipped unless run with administrative privileges, either
|
17
|
+
because they require it, or because they otherwise take too long.
|
18
|
+
* Gem related tasks in the Rakefile now assume Rubygems 2.x.
|
19
|
+
* Added an appveyor.yml file.
|
20
|
+
* The DemoDaemon example will create C:/Tmp if it doesn't already exist.
|
21
|
+
|
1
22
|
== 0.8.7 - 14-Jul-2014
|
2
23
|
* Fixed a bug in the SERVICE_DELAYED_AUTO_START_INFO struct. It now returns 0
|
3
24
|
or 1, though it still accepts true or false as arguments. Thanks go to
|
data/MANIFEST
CHANGED
@@ -3,11 +3,14 @@
|
|
3
3
|
* README
|
4
4
|
* Rakefile
|
5
5
|
* win32-service.gemspec
|
6
|
+
* certs/djberg96_pub.pem
|
6
7
|
* doc/daemon.txt
|
7
8
|
* doc/service.txt
|
8
9
|
* examples/demo_daemon.rb
|
9
10
|
* examples/demo_daemon_ctl.rb
|
10
11
|
* examples/demo_services.rb
|
12
|
+
* lib/win32-daemon.rb
|
13
|
+
* lib/win32-service.rb
|
11
14
|
* lib/win32/service.rb
|
12
15
|
* lib/win32/daemon.rb
|
13
16
|
* test/test_win32_daemon.rb
|
data/README
CHANGED
@@ -56,17 +56,11 @@
|
|
56
56
|
Add service_session_change hook
|
57
57
|
|
58
58
|
== Copyright
|
59
|
-
(C) 2003-
|
59
|
+
(C) 2003-2016, Daniel J. Berger, All Rights Reserved
|
60
60
|
|
61
61
|
== License
|
62
62
|
Artistic 2.0
|
63
63
|
|
64
|
-
== Contributions
|
65
|
-
Although this library is free, please consider having your company
|
66
|
-
setup a gittip if used by your company professionally.
|
67
|
-
|
68
|
-
http://www.gittip.com/djberg96/
|
69
|
-
|
70
64
|
== Warranty
|
71
65
|
This package is provided "as is" and without any express or
|
72
66
|
implied warranties, including, without limitation, the implied
|
data/Rakefile
CHANGED
@@ -12,13 +12,10 @@ CLEAN.include(
|
|
12
12
|
namespace 'gem' do
|
13
13
|
desc "Create the win32-service gem"
|
14
14
|
task :create => [:clean] do
|
15
|
+
require 'rubygems/package'
|
15
16
|
spec = eval(IO.read('win32-service.gemspec'))
|
16
|
-
|
17
|
-
|
18
|
-
else
|
19
|
-
require 'rubygems/package'
|
20
|
-
Gem::Package.build(spec)
|
21
|
-
end
|
17
|
+
spec.signing_key = File.join(Dir.home, '.ssh', 'gem-private_key.pem')
|
18
|
+
Gem::Package.build(spec, true)
|
22
19
|
end
|
23
20
|
|
24
21
|
desc "Install the win32-service gem"
|
data/appveyor.yml
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
version: '{build}'
|
2
|
+
branches:
|
3
|
+
only:
|
4
|
+
- ffi
|
5
|
+
skip_tags: true
|
6
|
+
clone_depth: 10
|
7
|
+
environment:
|
8
|
+
matrix:
|
9
|
+
- ruby_version: 193
|
10
|
+
ruby_dir: 1.9.1
|
11
|
+
- ruby_version: 200
|
12
|
+
ruby_dir: 2.0.0
|
13
|
+
- ruby_version: 200-x64
|
14
|
+
ruby_dir: 2.0.0
|
15
|
+
- ruby_version: 21
|
16
|
+
ruby_dir: 2.1.0
|
17
|
+
- ruby_version: 21-x64
|
18
|
+
ruby_dir: 2.1.0
|
19
|
+
- ruby_version: 22
|
20
|
+
ruby_dir: 2.2.0
|
21
|
+
- ruby_version: 22-x64
|
22
|
+
ruby_dir: 2.2.0
|
23
|
+
install:
|
24
|
+
- ps: >-
|
25
|
+
$env:path = "C:\Ruby" + $env:ruby_version + "\bin;" + $env:path
|
26
|
+
|
27
|
+
$tpath = "C:\Ruby" + $env:ruby_version + "\lib\ruby\" + $env:ruby_dir + "\test"
|
28
|
+
|
29
|
+
if ((test-path $tpath) -eq $True){ rm -recurse -force $tpath }
|
30
|
+
|
31
|
+
gem update --system > $null
|
32
|
+
|
33
|
+
if ((gem query -i ffi) -eq $False){ gem install ffi --no-document }
|
34
|
+
|
35
|
+
if ((gem query -i win32-security) -eq $False){ gem install win32-security --no-document }
|
36
|
+
|
37
|
+
if ((gem query -i test-unit -v ">= 3.0") -eq $False){ gem install test-unit --no-document }
|
38
|
+
cache:
|
39
|
+
- C:\Ruby193\lib\ruby\gems\1.9.1
|
40
|
+
- C:\Ruby200\lib\ruby\gems\2.0.0
|
41
|
+
- C:\Ruby200-x64\lib\ruby\gems\2.0.0
|
42
|
+
- C:\Ruby21\lib\ruby\gems\2.1.0
|
43
|
+
- C:\Ruby21-x64\lib\ruby\gems\2.1.0
|
44
|
+
- C:\Ruby22\lib\ruby\gems\2.2.0
|
45
|
+
- C:\Ruby22-x64\lib\ruby\gems\2.2.0
|
46
|
+
build: off
|
47
|
+
test_script:
|
48
|
+
- cmd: rake
|
@@ -0,0 +1,21 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MREwDwYDVQQDDAhkamJl
|
3
|
+
cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
|
4
|
+
MB4XDTE1MDkwMjIwNDkxOFoXDTE2MDkwMTIwNDkxOFowPzERMA8GA1UEAwwIZGpi
|
5
|
+
ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
|
6
|
+
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyTkvXqRp6hLs9eoJOS
|
7
|
+
Hmi8kRYbq9Vkf15/hMxJpotYMgJVHHWrmDcC5Dye2PbnXjTkKf266Zw0PtT9h+lI
|
8
|
+
S3ts9HO+vaCFSMwFFZmnWJSpQ3CNw2RcHxjWkk9yF7imEM8Kz9ojhiDXzBetdV6M
|
9
|
+
gr0lV/alUr7TNVBDngbXEfTWscyXh1qd7xZ4EcOdsDktCe5G45N/o3662tPQvJsi
|
10
|
+
FOF0CM/KuBsa/HL1/eoEmF4B3EKIRfTHrQ3hu20Kv3RJ88QM4ec2+0dd97uX693O
|
11
|
+
zv6981fyEg+aXLkxrkViM/tz2qR2ZE0jPhHTREPYeMEgptRkTmWSKAuLVWrJEfgl
|
12
|
+
DtkCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEwe
|
13
|
+
nn6bfJADmuIDiMSOzedOrL+xMB0GA1UdEQQWMBSBEmRqYmVyZzk2QGdtYWlsLmNv
|
14
|
+
bTAdBgNVHRIEFjAUgRJkamJlcmc5NkBnbWFpbC5jb20wDQYJKoZIhvcNAQEFBQAD
|
15
|
+
ggEBAHmNOCWoDVD75zHFueY0viwGDVP1BNGFC+yXcb7u2GlK+nEMCORqzURbYPf7
|
16
|
+
tL+/hzmePIRz7i30UM//64GI1NLv9jl7nIwjhPpXpf7/lu2I9hOTsvwSumb5UiKC
|
17
|
+
/sqBxI3sfj9pr79Wpv4MuikX1XPik7Ncb7NPsJPw06Lvyc3Hkg5X2XpPtLtS+Gr2
|
18
|
+
wKJnmzb5rIPS1cmsqv0M9LPWflzfwoZ/SpnmhagP+g05p8bRNKjZSA2iImM/GyYZ
|
19
|
+
EJYzxdPOrx2n6NYR3Hk+vHP0U7UBSveI6+qx+ndQYaeyCn+GRX2PKS9h66YF/Q1V
|
20
|
+
tGSHgAmcLlkdGgan182qsE/4kKM=
|
21
|
+
-----END CERTIFICATE-----
|
data/doc/daemon.txt
CHANGED
@@ -127,7 +127,7 @@ Daemon::IDLE
|
|
127
127
|
setup your own Daemon.
|
128
128
|
|
129
129
|
= Known Bugs
|
130
|
-
None known.
|
130
|
+
None known. Please report any bugs you find on the issue tracker at
|
131
131
|
https//github.com/djberg96/win32-service
|
132
132
|
|
133
133
|
= Future Plans
|
@@ -142,7 +142,7 @@ Daemon::IDLE
|
|
142
142
|
his patch that solved service responsiveness issues.
|
143
143
|
|
144
144
|
= Copyright
|
145
|
-
(C) 2003-
|
145
|
+
(C) 2003-2016 Daniel J. Berger, All Rights Reserved
|
146
146
|
|
147
147
|
= License
|
148
148
|
Artistic 2.0
|
data/doc/service.txt
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
An interface for MS Windows Services.
|
3
3
|
|
4
4
|
= Prerequisites
|
5
|
-
|
5
|
+
ffi 1.0 or later
|
6
6
|
|
7
7
|
This library is only supported for the Windows NT family of operating
|
8
8
|
systems, e.g. 2000, XP, 2003, etc. It is NOT supported (and won't
|
@@ -351,7 +351,7 @@ Service::ERROR_CRITICAL
|
|
351
351
|
Add ability to create or modify service failure actions.
|
352
352
|
|
353
353
|
= Copyright
|
354
|
-
(C) 2003-
|
354
|
+
(C) 2003-2016, Daniel J. Berger, All Rights Reserved
|
355
355
|
|
356
356
|
= Warranty
|
357
357
|
This package is provided "as is" and without any express or
|
data/examples/demo_daemon.rb
CHANGED
data/examples/demo_daemon_ctl.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# demo_daemon_ctl.rb
|
3
3
|
#
|
4
4
|
# This is a command line script for installing and/or running a small
|
5
|
-
# Ruby program as a service.
|
5
|
+
# Ruby program as a service. The service will simply write a small bit
|
6
6
|
# of text to a file every 20 seconds. It will also write some text to the
|
7
7
|
# file during the initialization (service_init) step.
|
8
8
|
#
|
@@ -10,7 +10,8 @@
|
|
10
10
|
# of the service_init hook, so don't be surprised if you see "one moment,
|
11
11
|
# start pending" about 10 times on the command line.
|
12
12
|
#
|
13
|
-
# The file in question is C:\
|
13
|
+
# The file in question is C:\Tmp\win32_daemon_test.log. Feel free to delete
|
14
|
+
# it when you're finished.
|
14
15
|
#
|
15
16
|
# To run the service, you must install it first.
|
16
17
|
#
|
data/lib/win32-daemon.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'win32/daemon'
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'win32/service'
|
data/lib/win32/daemon.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
require 'ffi'
|
1
|
+
require_relative 'windows/helper'
|
2
|
+
require_relative 'windows/constants'
|
3
|
+
require_relative 'windows/structs'
|
4
|
+
require_relative 'windows/functions'
|
7
5
|
|
8
6
|
# The Win32 module serves as a namespace only.
|
9
7
|
module Win32
|
@@ -11,14 +9,14 @@ module Win32
|
|
11
9
|
# The Daemon class
|
12
10
|
class Daemon
|
13
11
|
include Windows::ServiceConstants
|
14
|
-
include Windows::
|
15
|
-
include Windows::
|
12
|
+
include Windows::ServiceStructs
|
13
|
+
include Windows::ServiceFunctions
|
16
14
|
|
17
|
-
extend Windows::
|
18
|
-
extend Windows::
|
15
|
+
extend Windows::ServiceStructs
|
16
|
+
extend Windows::ServiceFunctions
|
19
17
|
|
20
18
|
# The version of this library
|
21
|
-
VERSION = '0.8.
|
19
|
+
VERSION = '0.8.8'
|
22
20
|
|
23
21
|
private
|
24
22
|
|
@@ -240,21 +238,21 @@ module Win32
|
|
240
238
|
service_init() if respond_to?('service_init')
|
241
239
|
|
242
240
|
# Create the event to signal the service to start.
|
243
|
-
@@hStartEvent = CreateEvent(nil,
|
241
|
+
@@hStartEvent = CreateEvent(nil, 1, 0, nil)
|
244
242
|
|
245
243
|
if @@hStartEvent == 0
|
246
244
|
raise SystemCallError.new('CreateEvent', FFI.errno)
|
247
245
|
end
|
248
246
|
|
249
247
|
# Create the event to signal the service to stop.
|
250
|
-
@@hStopEvent = CreateEvent(nil,
|
248
|
+
@@hStopEvent = CreateEvent(nil, 1, 0, nil)
|
251
249
|
|
252
250
|
if @@hStopEvent == 0
|
253
251
|
raise SystemCallError.new('CreateEvent', FFI.errno)
|
254
252
|
end
|
255
253
|
|
256
254
|
# Create the event to signal the service that stop has completed
|
257
|
-
@@hStopCompletedEvent = CreateEvent(nil,
|
255
|
+
@@hStopCompletedEvent = CreateEvent(nil, 1, 0, nil)
|
258
256
|
|
259
257
|
if @@hStopCompletedEvent == 0
|
260
258
|
raise SystemCallError.new('CreateEvent', FFI.errno)
|
@@ -270,7 +268,7 @@ module Win32
|
|
270
268
|
events.put_pointer(0, FFI::Pointer.new(hThread))
|
271
269
|
events.put_pointer(FFI::Pointer.size, FFI::Pointer.new(@@hStartEvent))
|
272
270
|
|
273
|
-
while ((index = WaitForMultipleObjects(2, events,
|
271
|
+
while ((index = WaitForMultipleObjects(2, events, 0, 1000)) == WAIT_TIMEOUT) do
|
274
272
|
end
|
275
273
|
|
276
274
|
if index == WAIT_FAILED
|
@@ -284,7 +282,7 @@ module Win32
|
|
284
282
|
|
285
283
|
thr = Thread.new do
|
286
284
|
begin
|
287
|
-
while(WaitForSingleObject(@@hStopEvent,
|
285
|
+
while(WaitForSingleObject(@@hStopEvent, 1000) == WAIT_TIMEOUT)
|
288
286
|
# Check to see if anything interesting has been signaled
|
289
287
|
case @@waiting_control_code
|
290
288
|
when SERVICE_CONTROL_PAUSE
|
data/lib/win32/service.rb
CHANGED
@@ -10,14 +10,14 @@ module Win32
|
|
10
10
|
# creating, starting, configuring or deleting services.
|
11
11
|
class Service
|
12
12
|
include Windows::ServiceConstants
|
13
|
-
include Windows::
|
14
|
-
include Windows::
|
13
|
+
include Windows::ServiceStructs
|
14
|
+
include Windows::ServiceFunctions
|
15
15
|
|
16
|
-
extend Windows::
|
17
|
-
extend Windows::
|
16
|
+
extend Windows::ServiceStructs
|
17
|
+
extend Windows::ServiceFunctions
|
18
18
|
|
19
19
|
# The version of the win32-service library
|
20
|
-
VERSION = '0.8.
|
20
|
+
VERSION = '0.8.8'
|
21
21
|
|
22
22
|
# SCM security and access rights
|
23
23
|
|
@@ -1085,22 +1085,24 @@ module Win32
|
|
1085
1085
|
end
|
1086
1086
|
rescue
|
1087
1087
|
# While being annoying, not being able to get a description is not exceptional
|
1088
|
-
warn "WARNING: Failed to
|
1088
|
+
warn "WARNING: Failed to retrieve description for the #{service_name} service."
|
1089
1089
|
description = ''
|
1090
1090
|
end
|
1091
1091
|
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1092
|
+
begin
|
1093
|
+
delayed_start_buf = get_config2_info(handle_scs, SERVICE_CONFIG_DELAYED_AUTO_START_INFO)
|
1094
|
+
if delayed_start_buf.is_a?(FFI::MemoryPointer)
|
1095
|
+
delayed_start_info = SERVICE_DELAYED_AUTO_START_INFO.new(delayed_start_buf)
|
1096
|
+
delayed_start = delayed_start_info[:fDelayedAutostart]
|
1097
|
+
else
|
1098
|
+
delayed_start = false
|
1099
|
+
end
|
1100
|
+
rescue
|
1101
|
+
warn "WARNING: Unable to get delayed auto start information for the #{service_name} service"
|
1102
|
+
delayed_start = nil
|
1099
1103
|
end
|
1100
1104
|
else
|
1101
|
-
|
1102
|
-
msg += "service could not be found."
|
1103
|
-
warn msg
|
1105
|
+
warn "WARNING: The registry entry for the #{service_name} service could not be found"
|
1104
1106
|
|
1105
1107
|
binary_path = nil
|
1106
1108
|
load_order = nil
|
@@ -1112,41 +1114,49 @@ module Win32
|
|
1112
1114
|
description = nil
|
1113
1115
|
end
|
1114
1116
|
|
1115
|
-
|
1117
|
+
begin
|
1118
|
+
buf2 = get_config2_info(handle_scs, SERVICE_CONFIG_FAILURE_ACTIONS)
|
1116
1119
|
|
1117
|
-
|
1118
|
-
|
1120
|
+
if buf2.is_a?(FFI::MemoryPointer)
|
1121
|
+
fail_struct = SERVICE_FAILURE_ACTIONS.new(buf2)
|
1119
1122
|
|
1120
|
-
|
1121
|
-
|
1123
|
+
reset_period = fail_struct[:dwResetPeriod]
|
1124
|
+
num_actions = fail_struct[:cActions]
|
1122
1125
|
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1126
|
+
if fail_struct[:lpRebootMsg].null?
|
1127
|
+
reboot_msg = nil
|
1128
|
+
else
|
1129
|
+
reboot_msg = fail_struct[:lpRebootMsg].read_string
|
1130
|
+
end
|
1128
1131
|
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1132
|
+
if fail_struct[:lpCommand].null?
|
1133
|
+
command = nil
|
1134
|
+
else
|
1135
|
+
command = fail_struct[:lpCommand].read_string
|
1136
|
+
end
|
1134
1137
|
|
1135
|
-
|
1138
|
+
actions = nil
|
1136
1139
|
|
1137
|
-
|
1138
|
-
|
1140
|
+
if num_actions > 0
|
1141
|
+
action_ptr = fail_struct[:lpsaActions]
|
1139
1142
|
|
1140
|
-
|
1143
|
+
actions = {}
|
1141
1144
|
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1145
|
+
num_actions.times{ |n|
|
1146
|
+
sc_action = SC_ACTION.new(action_ptr[n])
|
1147
|
+
delay = sc_action[:Delay]
|
1148
|
+
action_type = get_action_type(sc_action[:Type])
|
1149
|
+
actions[n+1] = {:action_type => action_type, :delay => delay}
|
1150
|
+
}
|
1151
|
+
end
|
1152
|
+
else
|
1153
|
+
reset_period = nil
|
1154
|
+
reboot_msg = nil
|
1155
|
+
command = nil
|
1156
|
+
actions = nil
|
1148
1157
|
end
|
1149
|
-
|
1158
|
+
rescue
|
1159
|
+
warn "WARNING: Unable to retrieve failure actions for the #{service_name} service"
|
1150
1160
|
reset_period = nil
|
1151
1161
|
reboot_msg = nil
|
1152
1162
|
command = nil
|
@@ -1242,7 +1252,7 @@ module Win32
|
|
1242
1252
|
# Enable shutdown privilege in access token of this process
|
1243
1253
|
bool = AdjustTokenPrivileges(
|
1244
1254
|
token_handle,
|
1245
|
-
|
1255
|
+
0,
|
1246
1256
|
tkp,
|
1247
1257
|
tkp.size,
|
1248
1258
|
nil,
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'ffi'
|
2
2
|
|
3
3
|
module Windows
|
4
|
-
module
|
4
|
+
module ServiceFunctions
|
5
5
|
extend FFI::Library
|
6
6
|
|
7
7
|
# Make FFI functions private
|
@@ -22,7 +22,7 @@ module Windows
|
|
22
22
|
ffi_lib :kernel32
|
23
23
|
|
24
24
|
attach_pfunc :CloseHandle, [:handle], :bool
|
25
|
-
attach_pfunc :CreateEvent, :CreateEventA, [:ptr, :
|
25
|
+
attach_pfunc :CreateEvent, :CreateEventA, [:ptr, :int, :int, :str], :handle
|
26
26
|
attach_pfunc :CreateThread, [:ptr, :size_t, :ptr, :ptr, :dword, :ptr], :handle, :blocking => true
|
27
27
|
attach_pfunc :EnterCriticalSection, [:ptr], :void
|
28
28
|
attach_pfunc :FormatMessage, :FormatMessageA, [:ulong, :ptr, :ulong, :ulong, :str, :ulong, :ptr], :ulong
|
@@ -31,13 +31,13 @@ module Windows
|
|
31
31
|
attach_pfunc :LeaveCriticalSection, [:ptr], :void
|
32
32
|
attach_pfunc :SetEvent, [:handle], :bool
|
33
33
|
attach_pfunc :WaitForSingleObject, [:handle, :dword], :dword, :blocking => true
|
34
|
-
attach_pfunc :WaitForMultipleObjects, [:dword, :ptr, :
|
34
|
+
attach_pfunc :WaitForMultipleObjects, [:dword, :ptr, :int, :dword], :dword
|
35
35
|
|
36
36
|
ffi_lib :advapi32
|
37
37
|
|
38
38
|
callback :handler_ex, [:ulong, :ulong, :ptr, :ptr], :void
|
39
39
|
|
40
|
-
attach_pfunc :AdjustTokenPrivileges, [:handle, :
|
40
|
+
attach_pfunc :AdjustTokenPrivileges, [:handle, :int, :ptr, :dword, :ptr, :ptr], :bool
|
41
41
|
attach_pfunc :CloseServiceHandle, [:handle], :bool
|
42
42
|
|
43
43
|
attach_pfunc :ChangeServiceConfig, :ChangeServiceConfigA,
|
data/test/test_win32_daemon.rb
CHANGED
data/test/test_win32_service.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
##########################################################################
|
2
2
|
# test_win32_service.rb
|
3
3
|
#
|
4
|
-
# Tests for the Win32::Service class.
|
4
|
+
# Tests for the Win32::Service class. Some tests are skipped unless
|
5
|
+
# run with admin privileges either because they are somewhat invasive,
|
6
|
+
# or because they take too long.
|
5
7
|
##########################################################################
|
6
8
|
require 'test-unit'
|
7
9
|
require 'win32/security'
|
@@ -20,29 +22,39 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
20
22
|
@service_name = 'stisvc'
|
21
23
|
@service_stat = nil
|
22
24
|
@services = []
|
25
|
+
@elevated = Win32::Security.elevated_security?
|
23
26
|
|
24
27
|
@singleton_methods = Win32::Service.methods.map{ |m| m.to_s }
|
25
28
|
@instance_methods = Win32::Service.instance_methods.map{ |m| m.to_s }
|
26
29
|
end
|
27
30
|
|
31
|
+
def omit_unless_elevated
|
32
|
+
omit_unless(@elevated, "Skipped unless run with admin privileges")
|
33
|
+
end
|
34
|
+
|
28
35
|
def start_service(service)
|
29
36
|
status = Win32::Service.status(@service_name).current_state
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
37
|
+
|
38
|
+
if @elevated
|
39
|
+
if status == 'paused'
|
40
|
+
Win32::Service.resume(service)
|
41
|
+
else
|
42
|
+
unless ['running', 'start pending'].include?(status)
|
43
|
+
Win32::Service.start(service)
|
44
|
+
end
|
35
45
|
end
|
46
|
+
wait_for_status('running')
|
36
47
|
end
|
37
|
-
wait_for_status('running')
|
38
48
|
end
|
39
49
|
|
40
50
|
def stop_service(service)
|
41
51
|
status = Win32::Service.status(@service_name).current_state
|
42
|
-
|
43
|
-
|
52
|
+
if @elevated
|
53
|
+
unless ['stopped', 'stop pending'].include?(status)
|
54
|
+
Win32::Service.stop(service)
|
55
|
+
end
|
56
|
+
wait_for_status('stopped')
|
44
57
|
end
|
45
|
-
wait_for_status('stopped')
|
46
58
|
end
|
47
59
|
|
48
60
|
# Helper method that waits for a status to change its state since state
|
@@ -52,14 +64,23 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
52
64
|
end
|
53
65
|
|
54
66
|
test "version number is expected value" do
|
55
|
-
assert_equal('0.8.
|
67
|
+
assert_equal('0.8.8', Win32::Service::VERSION)
|
56
68
|
end
|
57
69
|
|
58
70
|
test "services basic functionality" do
|
59
71
|
assert_respond_to(Win32::Service, :services)
|
72
|
+
end
|
73
|
+
|
74
|
+
test "services with no arguments works as expected" do
|
60
75
|
assert_nothing_raised{ Win32::Service.services }
|
61
|
-
|
62
|
-
|
76
|
+
end
|
77
|
+
|
78
|
+
test "services with explicit host works as expected" do
|
79
|
+
assert_nothing_raised{ Win32::Service.services(@@host) }
|
80
|
+
end
|
81
|
+
|
82
|
+
test "services with explicit host and group works as expected" do
|
83
|
+
assert_nothing_raised{ Win32::Service.services(@@host, 'network') }
|
63
84
|
end
|
64
85
|
|
65
86
|
test "services method returns an array without a block" do
|
@@ -87,6 +108,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
87
108
|
end
|
88
109
|
|
89
110
|
test "a valid hostname must be provided or an error is raised" do
|
111
|
+
omit_unless_elevated
|
90
112
|
assert_raise(SystemCallError){ Win32::Service.services('bogus') }
|
91
113
|
end
|
92
114
|
|
@@ -99,11 +121,12 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
99
121
|
end
|
100
122
|
|
101
123
|
test "delete method raises an error if a bogus service name is provided" do
|
102
|
-
|
124
|
+
omit_unless_elevated
|
103
125
|
assert_raise(SystemCallError){ Win32::Service.delete('bogus') }
|
104
126
|
end
|
105
127
|
|
106
128
|
test "delete method raises an error if a bogus host name is provided" do
|
129
|
+
omit_unless_elevated
|
107
130
|
assert_raise(SystemCallError){ Win32::Service.delete('bogus', 'bogus') }
|
108
131
|
end
|
109
132
|
|
@@ -120,7 +143,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
120
143
|
end
|
121
144
|
|
122
145
|
test "pause and resume work as expected" do
|
123
|
-
|
146
|
+
omit_unless_elevated
|
124
147
|
start_service(@service_name)
|
125
148
|
|
126
149
|
assert_nothing_raised{ Win32::Service.pause(@service_name) }
|
@@ -131,7 +154,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
131
154
|
end
|
132
155
|
|
133
156
|
test "pausing an already paused service is harmless" do
|
134
|
-
|
157
|
+
omit_unless_elevated
|
135
158
|
start_service(@service_name)
|
136
159
|
|
137
160
|
assert_nothing_raised{ Win32::Service.pause(@service_name) }
|
@@ -148,6 +171,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
148
171
|
end
|
149
172
|
|
150
173
|
test "pausing a service on an unrecognized host raises an error" do
|
174
|
+
omit_unless_elevated
|
151
175
|
assert_raise(SystemCallError){ Win32::Service.pause('W32Time', 'bogus') }
|
152
176
|
end
|
153
177
|
|
@@ -164,6 +188,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
164
188
|
end
|
165
189
|
|
166
190
|
test "resume method with an unrecognized host name raises an error" do
|
191
|
+
omit_unless_elevated
|
167
192
|
assert_raise(SystemCallError){ Win32::Service.resume('W32Time', 'bogus') }
|
168
193
|
end
|
169
194
|
|
@@ -180,7 +205,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
180
205
|
end
|
181
206
|
|
182
207
|
test "stop and start methods work as expected" do
|
183
|
-
|
208
|
+
omit_unless_elevated
|
184
209
|
start_service(@service_name)
|
185
210
|
|
186
211
|
assert_nothing_raised{ Win32::Service.stop(@service_name) }
|
@@ -191,7 +216,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
191
216
|
end
|
192
217
|
|
193
218
|
test "attempting to stop a stopped service raises an error" do
|
194
|
-
|
219
|
+
omit_unless_elevated
|
195
220
|
start_service(@service_name)
|
196
221
|
|
197
222
|
assert_nothing_raised{ Win32::Service.stop(@service_name) }
|
@@ -210,6 +235,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
210
235
|
end
|
211
236
|
|
212
237
|
test "stop method raises an error if the host is unrecognized" do
|
238
|
+
omit_unless_elevated
|
213
239
|
assert_raise(SystemCallError){ Win32::Service.stop('W32Time', 'bogus') }
|
214
240
|
end
|
215
241
|
|
@@ -222,7 +248,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
222
248
|
end
|
223
249
|
|
224
250
|
test "attempting to start a running service raises an error" do
|
225
|
-
|
251
|
+
omit_unless_elevated
|
226
252
|
start_service(@service_name)
|
227
253
|
assert_raise(SystemCallError){ Win32::Service.start(@service_name) }
|
228
254
|
end
|
@@ -232,6 +258,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
232
258
|
end
|
233
259
|
|
234
260
|
test "attempting to start a service on an unknown host raises an error" do
|
261
|
+
omit_unless_elevated
|
235
262
|
assert_raise(SystemCallError){ Win32::Service.start('bogus', 'bogus') }
|
236
263
|
end
|
237
264
|
|
@@ -244,6 +271,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
244
271
|
end
|
245
272
|
|
246
273
|
test "stop raises an error with an unrecognized host" do
|
274
|
+
omit_unless_elevated
|
247
275
|
assert_raise(SystemCallError){ Win32::Service.stop('W32Time', 'bogus') }
|
248
276
|
end
|
249
277
|
|
@@ -281,6 +309,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
281
309
|
end
|
282
310
|
|
283
311
|
test "get_service_name raises an error if a bogus host is provided" do
|
312
|
+
omit_unless_elevated
|
284
313
|
assert_raise(SystemCallError){ Win32::Service.get_service_name('foo', 'bogus') }
|
285
314
|
end
|
286
315
|
|
@@ -312,6 +341,7 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
312
341
|
end
|
313
342
|
|
314
343
|
test "get_display_name raises an error if a bad host name is provided" do
|
344
|
+
omit_unless_elevated
|
315
345
|
assert_raise(SystemCallError){ Win32::Service.get_display_name('W32Time', 'bogus') }
|
316
346
|
end
|
317
347
|
|
@@ -335,9 +365,8 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
335
365
|
end
|
336
366
|
|
337
367
|
test "exists method raises an error if a bogus host is passed" do
|
338
|
-
|
339
|
-
|
340
|
-
}
|
368
|
+
omit_unless_elevated
|
369
|
+
assert_raises(SystemCallError){ Win32::Service.exists?('foo', 'bogus') }
|
341
370
|
end
|
342
371
|
|
343
372
|
test "exists method only accepts up to two arguments" do
|
@@ -424,12 +453,14 @@ class TC_Win32_Service < Test::Unit::TestCase
|
|
424
453
|
@@host = nil
|
425
454
|
status = Win32::Service.status(@@service_name).current_state
|
426
455
|
|
427
|
-
if
|
428
|
-
|
429
|
-
|
456
|
+
if @elevated
|
457
|
+
if status == 'paused'
|
458
|
+
Win32::Service.resume(@@service_name)
|
459
|
+
end
|
430
460
|
|
431
|
-
|
432
|
-
|
461
|
+
unless ['running', 'start pending'].include?(status)
|
462
|
+
Win32::Service.start(@@service_name)
|
463
|
+
end
|
433
464
|
end
|
434
465
|
|
435
466
|
@@elevated = nil
|
@@ -4,6 +4,7 @@
|
|
4
4
|
# Test suite that validates the Service.configure method.
|
5
5
|
#######################################################################
|
6
6
|
require 'test-unit'
|
7
|
+
require 'win32/security'
|
7
8
|
require 'win32/service'
|
8
9
|
|
9
10
|
class TC_Win32_Service_Configure < Test::Unit::TestCase
|
@@ -11,10 +12,12 @@ class TC_Win32_Service_Configure < Test::Unit::TestCase
|
|
11
12
|
@@service = "notepad_service"
|
12
13
|
@@command = "C:\\windows\\system32\\notepad.exe"
|
13
14
|
|
14
|
-
Win32::
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
if Win32::Security.elevated_security?
|
16
|
+
Win32::Service.new(
|
17
|
+
:service_name => @@service,
|
18
|
+
:binary_path_name => @@command
|
19
|
+
)
|
20
|
+
end
|
18
21
|
end
|
19
22
|
|
20
23
|
def config_info
|
@@ -39,7 +42,8 @@ class TC_Win32_Service_Configure < Test::Unit::TestCase
|
|
39
42
|
end
|
40
43
|
|
41
44
|
def setup
|
42
|
-
@
|
45
|
+
@elevated = Win32::Security.elevated_security?
|
46
|
+
@info = Win32::Service.config_info(@@service) if @elevated
|
43
47
|
end
|
44
48
|
|
45
49
|
test "configure method is defined" do
|
@@ -47,24 +51,28 @@ class TC_Win32_Service_Configure < Test::Unit::TestCase
|
|
47
51
|
end
|
48
52
|
|
49
53
|
test "configuring the service type works as expected" do
|
54
|
+
omit_unless(@elevated)
|
50
55
|
assert_equal('own process', config_info.service_type)
|
51
56
|
service_configure(:service_type => Win32::Service::WIN32_SHARE_PROCESS)
|
52
57
|
assert_equal('share process', config_info.service_type)
|
53
58
|
end
|
54
59
|
|
55
60
|
test "configuring the description works as expected" do
|
61
|
+
omit_unless(@elevated)
|
56
62
|
assert_equal('', full_info.description)
|
57
63
|
service_configure(:description => 'test service')
|
58
64
|
assert_equal('test service', full_info.description)
|
59
65
|
end
|
60
66
|
|
61
67
|
test "configuring the start type works as expected" do
|
68
|
+
omit_unless(@elevated)
|
62
69
|
assert_equal('demand start', config_info.start_type)
|
63
70
|
service_configure(:start_type => Win32::Service::DISABLED)
|
64
71
|
assert_equal('disabled', config_info.start_type)
|
65
72
|
end
|
66
73
|
|
67
74
|
test "service start can be delayed" do
|
75
|
+
omit_unless(@elevated)
|
68
76
|
service_configure(:start_type => Win32::Service::AUTO_START, :delayed_start => true)
|
69
77
|
assert_equal(1, full_info.delayed_start)
|
70
78
|
end
|
@@ -89,10 +97,13 @@ class TC_Win32_Service_Configure < Test::Unit::TestCase
|
|
89
97
|
|
90
98
|
def teardown
|
91
99
|
@info = nil
|
100
|
+
@elevated = nil
|
92
101
|
end
|
93
102
|
|
94
103
|
def self.shutdown
|
95
|
-
Win32::Service.
|
104
|
+
if Win32::Service.exists?(@@service) && Win32::Security.elevated_security?
|
105
|
+
Win32::Service.delete(@@service)
|
106
|
+
end
|
96
107
|
@@service = nil
|
97
108
|
@@command = nil
|
98
109
|
end
|
@@ -5,6 +5,7 @@
|
|
5
5
|
# a dummy (notepad) service. It won't actually run of course.
|
6
6
|
########################################################################
|
7
7
|
require 'test-unit'
|
8
|
+
require 'win32/security'
|
8
9
|
require 'win32/service'
|
9
10
|
|
10
11
|
class TC_Win32_Service_Create < Test::Unit::TestCase
|
@@ -13,28 +14,34 @@ class TC_Win32_Service_Create < Test::Unit::TestCase
|
|
13
14
|
@@service2 = "notepad_service2"
|
14
15
|
@@command = "C:\\windows\\system32\\notepad.exe"
|
15
16
|
|
16
|
-
Win32::
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
17
|
+
if Win32::Security.elevated_security?
|
18
|
+
Win32::Service.new(
|
19
|
+
:service_name => @@service1,
|
20
|
+
:binary_path_name => @@command
|
21
|
+
)
|
22
|
+
|
23
|
+
Win32::Service.new(
|
24
|
+
:service_name => @@service2,
|
25
|
+
:display_name => 'Notepad Test',
|
26
|
+
:desired_access => Win32::Service::ALL_ACCESS,
|
27
|
+
:service_type => Win32::Service::WIN32_OWN_PROCESS,
|
28
|
+
:start_type => Win32::Service::DISABLED,
|
29
|
+
:error_control => Win32::Service::ERROR_IGNORE,
|
30
|
+
:binary_path_name => @@command,
|
31
|
+
:load_order_group => 'Network',
|
32
|
+
:dependencies => 'W32Time',
|
33
|
+
:description => 'Test service. Please delete me'
|
34
|
+
)
|
35
|
+
end
|
33
36
|
end
|
34
37
|
|
35
38
|
def setup
|
36
|
-
@
|
37
|
-
|
39
|
+
@elevated = Win32::Security.elevated_security?
|
40
|
+
|
41
|
+
if @elevated
|
42
|
+
@info1 = Win32::Service.config_info(@@service1)
|
43
|
+
@info2 = Win32::Service.config_info(@@service2)
|
44
|
+
end
|
38
45
|
end
|
39
46
|
|
40
47
|
test "constructor basic functionality" do
|
@@ -48,48 +55,59 @@ class TC_Win32_Service_Create < Test::Unit::TestCase
|
|
48
55
|
end
|
49
56
|
|
50
57
|
test "ensure services were created in startup method" do
|
58
|
+
omit_unless(@elevated)
|
51
59
|
notify "If this test fails then remaining results are meaningless."
|
52
60
|
assert_true(Win32::Service.exists?(@@service1))
|
53
61
|
assert_true(Win32::Service.exists?(@@service2))
|
54
62
|
end
|
55
63
|
|
56
64
|
test "expected service type configuration information" do
|
65
|
+
omit_unless(@elevated)
|
57
66
|
assert_equal('own process', @info1.service_type)
|
58
67
|
end
|
59
68
|
|
60
69
|
test "expected start type configuration information" do
|
70
|
+
omit_unless(@elevated)
|
61
71
|
assert_equal('demand start', @info1.start_type)
|
62
72
|
end
|
63
73
|
|
64
74
|
test "expected error control configuration information" do
|
75
|
+
omit_unless(@elevated)
|
65
76
|
assert_equal('normal', @info1.error_control)
|
66
77
|
end
|
67
78
|
|
68
79
|
test "expected binary path name configuration information" do
|
80
|
+
omit_unless(@elevated)
|
69
81
|
assert_equal(@@command, @info1.binary_path_name)
|
70
82
|
end
|
71
83
|
|
72
84
|
test "expected load order group configuration information" do
|
85
|
+
omit_unless(@elevated)
|
73
86
|
assert_equal('', @info1.load_order_group)
|
74
87
|
end
|
75
88
|
|
76
89
|
test "expected tag id configuration information" do
|
90
|
+
omit_unless(@elevated)
|
77
91
|
assert_equal(0, @info1.tag_id)
|
78
92
|
end
|
79
93
|
|
80
94
|
test "expected dependency configuration information" do
|
95
|
+
omit_unless(@elevated)
|
81
96
|
assert_equal([], @info1.dependencies)
|
82
97
|
end
|
83
98
|
|
84
99
|
test "expected service start time configuration information" do
|
100
|
+
omit_unless(@elevated)
|
85
101
|
assert_equal('LocalSystem', @info1.service_start_name)
|
86
102
|
end
|
87
103
|
|
88
104
|
test "expected display name configuration information" do
|
105
|
+
omit_unless(@elevated)
|
89
106
|
assert_equal('notepad_service1', @info1.display_name)
|
90
107
|
end
|
91
108
|
|
92
109
|
test "configuration information options are set properly for service 2" do
|
110
|
+
omit_unless(@elevated)
|
93
111
|
assert_equal('own process', @info2.service_type)
|
94
112
|
assert_equal('disabled', @info2.start_type)
|
95
113
|
assert_equal('ignore', @info2.error_control)
|
@@ -114,13 +132,19 @@ class TC_Win32_Service_Create < Test::Unit::TestCase
|
|
114
132
|
end
|
115
133
|
|
116
134
|
def teardown
|
117
|
-
@
|
118
|
-
|
135
|
+
if @elevated
|
136
|
+
@info1 = nil
|
137
|
+
@info2 = nil
|
138
|
+
end
|
139
|
+
|
140
|
+
@elevated = nil
|
119
141
|
end
|
120
142
|
|
121
143
|
def self.shutdown
|
122
|
-
|
123
|
-
|
144
|
+
if Win32::Security.elevated_security?
|
145
|
+
Win32::Service.delete(@@service1) if Win32::Service.exists?(@@service1)
|
146
|
+
Win32::Service.delete(@@service2) if Win32::Service.exists?(@@service2)
|
147
|
+
end
|
124
148
|
|
125
149
|
@@service1 = nil
|
126
150
|
@@service2 = nil
|
@@ -71,106 +71,107 @@ class TC_Win32_ServiceInfo_Struct < Test::Unit::TestCase
|
|
71
71
|
]
|
72
72
|
end
|
73
73
|
|
74
|
-
|
74
|
+
test "service_name basic functionality" do
|
75
75
|
assert_respond_to(@service_info, :service_name)
|
76
76
|
assert_kind_of(String, @service_info.service_name)
|
77
77
|
end
|
78
78
|
|
79
|
-
|
79
|
+
test "display_name basic functionality" do
|
80
80
|
assert_respond_to(@service_info, :display_name)
|
81
81
|
assert_kind_of(String, @service_info.display_name)
|
82
82
|
end
|
83
83
|
|
84
|
-
|
84
|
+
test "service_type basic functionality" do
|
85
85
|
assert_respond_to(@service_info, :service_type)
|
86
86
|
assert(@types.include?(@service_info.service_type))
|
87
87
|
end
|
88
88
|
|
89
|
-
|
89
|
+
test "current_state basic functionality" do
|
90
90
|
assert_respond_to(@service_info, :current_state)
|
91
91
|
assert(@states.include?(@service_info.current_state))
|
92
92
|
end
|
93
93
|
|
94
|
-
|
94
|
+
test "controls_accepted basic functionality" do
|
95
95
|
assert_respond_to(@service_info, :controls_accepted)
|
96
96
|
assert_kind_of(Array, @service_info.controls_accepted)
|
97
|
+
end
|
98
|
+
|
99
|
+
test "controls_accepted returns expected values" do
|
97
100
|
assert_false(@service_info.controls_accepted.empty?)
|
98
|
-
@service_info.controls_accepted.each{ |
|
99
|
-
assert_true(@controls.include?(control))
|
100
|
-
}
|
101
|
+
@service_info.controls_accepted.each{ |c| assert_true(@controls.include?(c)) }
|
101
102
|
end
|
102
103
|
|
103
|
-
|
104
|
+
test "win32_exit_code basic functionality" do
|
104
105
|
assert_respond_to(@service_info, :win32_exit_code)
|
105
106
|
assert_kind_of(Fixnum, @service_info.win32_exit_code)
|
106
107
|
end
|
107
108
|
|
108
|
-
|
109
|
+
test "service_specific_exit_code basic functionality" do
|
109
110
|
assert_respond_to(@service_info, :service_specific_exit_code)
|
110
111
|
assert_kind_of(Fixnum, @service_info.service_specific_exit_code)
|
111
112
|
end
|
112
113
|
|
113
|
-
|
114
|
+
test "check_point basic functionality" do
|
114
115
|
assert_respond_to(@service_info, :check_point)
|
115
116
|
assert_kind_of(Fixnum, @service_info.check_point)
|
116
117
|
end
|
117
118
|
|
118
|
-
|
119
|
+
test "wait_hint basic functionality" do
|
119
120
|
assert_respond_to(@service_info, :wait_hint)
|
120
121
|
assert_kind_of(Fixnum, @service_info.wait_hint)
|
121
122
|
end
|
122
123
|
|
123
|
-
|
124
|
+
test "binary_path_name basic functionality" do
|
124
125
|
assert_respond_to(@service_info, :binary_path_name)
|
125
126
|
assert_kind_of(String, @service_info.binary_path_name)
|
126
127
|
end
|
127
128
|
|
128
|
-
|
129
|
+
test "start_type basic functionality" do
|
129
130
|
assert_respond_to(@service_info, :start_type)
|
130
131
|
assert(@start_types.include?(@service_info.start_type))
|
131
132
|
end
|
132
133
|
|
133
|
-
|
134
|
+
test "error_control basic functionality" do
|
134
135
|
assert_respond_to(@service_info, :error_control)
|
135
136
|
assert(@error_controls.include?(@service_info.error_control))
|
136
137
|
end
|
137
138
|
|
138
|
-
|
139
|
+
test "load_order_group basic functionality" do
|
139
140
|
assert_respond_to(@service_info, :load_order_group)
|
140
141
|
assert_kind_of(String, @service_info.load_order_group)
|
141
142
|
end
|
142
143
|
|
143
|
-
|
144
|
+
test "tag_id basic functionality" do
|
144
145
|
assert_respond_to(@service_info, :tag_id)
|
145
146
|
assert_kind_of(Fixnum, @service_info.tag_id)
|
146
147
|
end
|
147
148
|
|
148
|
-
|
149
|
+
test "start_name basic functionality" do
|
149
150
|
assert_respond_to(@service_info, :start_name)
|
150
151
|
assert_kind_of(String, @service_info.start_name)
|
151
152
|
end
|
152
153
|
|
153
|
-
|
154
|
+
test "dependencies basic functionality" do
|
154
155
|
assert_respond_to(@service_info, :dependencies)
|
155
156
|
assert_kind_of(Array, @service_info.dependencies)
|
156
157
|
end
|
157
158
|
|
158
|
-
|
159
|
+
test "description basic functionality" do
|
159
160
|
assert_respond_to(@service_info, :description)
|
160
161
|
assert_kind_of(String, @service_info.description)
|
161
162
|
end
|
162
163
|
|
163
|
-
|
164
|
+
test "interactive basic functionality" do
|
164
165
|
assert_respond_to(@service_info, :interactive)
|
165
166
|
assert_boolean(@service_info.interactive)
|
166
167
|
end
|
167
168
|
|
168
|
-
|
169
|
+
test "service_flags basic functionality" do
|
169
170
|
assert_respond_to(@service_info, :service_flags)
|
170
171
|
assert([0,1].include?(@service_info.service_flags))
|
171
172
|
end
|
172
173
|
|
173
|
-
|
174
|
+
test "delayed_start basic functionality" do
|
174
175
|
assert_respond_to(@service_info, :delayed_start)
|
175
176
|
assert([0,1].include?(@service_info.delayed_start))
|
176
177
|
end
|
data/win32-service.gemspec
CHANGED
@@ -2,13 +2,14 @@ require 'rubygems'
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'win32-service'
|
5
|
-
spec.version = '0.8.
|
5
|
+
spec.version = '0.8.8'
|
6
6
|
spec.authors = ['Daniel J. Berger', 'Park Heesob']
|
7
7
|
spec.license = 'Artistic 2.0'
|
8
8
|
spec.email = 'djberg96@gmail.com'
|
9
9
|
spec.homepage = 'http://github.com/djberg96/win32-service'
|
10
10
|
spec.summary = 'An interface for MS Windows services'
|
11
11
|
spec.test_files = Dir['test/test*.rb']
|
12
|
+
spec.cert_chain = Dir['certs/*']
|
12
13
|
|
13
14
|
spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
|
14
15
|
|
@@ -23,6 +24,7 @@ Gem::Specification.new do |spec|
|
|
23
24
|
spec.add_dependency('ffi')
|
24
25
|
spec.add_development_dependency('test-unit')
|
25
26
|
spec.add_development_dependency('rake')
|
27
|
+
spec.add_development_dependency('win32-security')
|
26
28
|
|
27
29
|
spec.description = <<-EOF
|
28
30
|
The win32-service library provides a Ruby interface to services on
|
metadata
CHANGED
@@ -1,15 +1,37 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win32-service
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
8
8
|
- Park Heesob
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
|
-
cert_chain:
|
12
|
-
|
11
|
+
cert_chain:
|
12
|
+
- |
|
13
|
+
-----BEGIN CERTIFICATE-----
|
14
|
+
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MREwDwYDVQQDDAhkamJl
|
15
|
+
cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
|
16
|
+
MB4XDTE1MDkwMjIwNDkxOFoXDTE2MDkwMTIwNDkxOFowPzERMA8GA1UEAwwIZGpi
|
17
|
+
ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
|
18
|
+
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyTkvXqRp6hLs9eoJOS
|
19
|
+
Hmi8kRYbq9Vkf15/hMxJpotYMgJVHHWrmDcC5Dye2PbnXjTkKf266Zw0PtT9h+lI
|
20
|
+
S3ts9HO+vaCFSMwFFZmnWJSpQ3CNw2RcHxjWkk9yF7imEM8Kz9ojhiDXzBetdV6M
|
21
|
+
gr0lV/alUr7TNVBDngbXEfTWscyXh1qd7xZ4EcOdsDktCe5G45N/o3662tPQvJsi
|
22
|
+
FOF0CM/KuBsa/HL1/eoEmF4B3EKIRfTHrQ3hu20Kv3RJ88QM4ec2+0dd97uX693O
|
23
|
+
zv6981fyEg+aXLkxrkViM/tz2qR2ZE0jPhHTREPYeMEgptRkTmWSKAuLVWrJEfgl
|
24
|
+
DtkCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEwe
|
25
|
+
nn6bfJADmuIDiMSOzedOrL+xMB0GA1UdEQQWMBSBEmRqYmVyZzk2QGdtYWlsLmNv
|
26
|
+
bTAdBgNVHRIEFjAUgRJkamJlcmc5NkBnbWFpbC5jb20wDQYJKoZIhvcNAQEFBQAD
|
27
|
+
ggEBAHmNOCWoDVD75zHFueY0viwGDVP1BNGFC+yXcb7u2GlK+nEMCORqzURbYPf7
|
28
|
+
tL+/hzmePIRz7i30UM//64GI1NLv9jl7nIwjhPpXpf7/lu2I9hOTsvwSumb5UiKC
|
29
|
+
/sqBxI3sfj9pr79Wpv4MuikX1XPik7Ncb7NPsJPw06Lvyc3Hkg5X2XpPtLtS+Gr2
|
30
|
+
wKJnmzb5rIPS1cmsqv0M9LPWflzfwoZ/SpnmhagP+g05p8bRNKjZSA2iImM/GyYZ
|
31
|
+
EJYzxdPOrx2n6NYR3Hk+vHP0U7UBSveI6+qx+ndQYaeyCn+GRX2PKS9h66YF/Q1V
|
32
|
+
tGSHgAmcLlkdGgan182qsE/4kKM=
|
33
|
+
-----END CERTIFICATE-----
|
34
|
+
date: 2016-06-25 00:00:00.000000000 Z
|
13
35
|
dependencies:
|
14
36
|
- !ruby/object:Gem::Dependency
|
15
37
|
name: ffi
|
@@ -53,6 +75,20 @@ dependencies:
|
|
53
75
|
- - ">="
|
54
76
|
- !ruby/object:Gem::Version
|
55
77
|
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: win32-security
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
type: :development
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
56
92
|
description: |2
|
57
93
|
The win32-service library provides a Ruby interface to services on
|
58
94
|
MS Windows. You can create new services, or control, configure and
|
@@ -70,21 +106,32 @@ extra_rdoc_files:
|
|
70
106
|
- doc/service.txt
|
71
107
|
- doc/daemon.txt
|
72
108
|
files:
|
109
|
+
- appveyor.yml
|
110
|
+
- certs
|
111
|
+
- certs/djberg96_pub.pem
|
73
112
|
- CHANGES
|
74
|
-
-
|
75
|
-
- README
|
76
|
-
- Rakefile
|
113
|
+
- doc
|
77
114
|
- doc/daemon.txt
|
78
115
|
- doc/service.txt
|
116
|
+
- examples
|
79
117
|
- examples/demo_daemon.rb
|
80
118
|
- examples/demo_daemon_ctl.rb
|
81
119
|
- examples/demo_services.rb
|
120
|
+
- lib
|
121
|
+
- lib/win32
|
82
122
|
- lib/win32/daemon.rb
|
83
123
|
- lib/win32/service.rb
|
124
|
+
- lib/win32/windows
|
84
125
|
- lib/win32/windows/constants.rb
|
85
126
|
- lib/win32/windows/functions.rb
|
86
127
|
- lib/win32/windows/helper.rb
|
87
128
|
- lib/win32/windows/structs.rb
|
129
|
+
- lib/win32-daemon.rb
|
130
|
+
- lib/win32-service.rb
|
131
|
+
- MANIFEST
|
132
|
+
- Rakefile
|
133
|
+
- README
|
134
|
+
- test
|
88
135
|
- test/test_win32_daemon.rb
|
89
136
|
- test/test_win32_service.rb
|
90
137
|
- test/test_win32_service_configure.rb
|
@@ -112,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
159
|
version: '0'
|
113
160
|
requirements: []
|
114
161
|
rubyforge_project:
|
115
|
-
rubygems_version: 2.4
|
162
|
+
rubygems_version: 2.6.4
|
116
163
|
signing_key:
|
117
164
|
specification_version: 4
|
118
165
|
summary: An interface for MS Windows services
|
metadata.gz.sig
ADDED
Binary file
|