win32-service 0.7.0-x86-mswin32-60 → 0.7.1-x86-mswin32-60
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +247 -238
- data/MANIFEST +18 -18
- data/README +74 -45
- data/Rakefile +139 -128
- data/doc/daemon.txt +157 -157
- data/doc/service.txt +365 -368
- data/examples/demo_daemon.rb +89 -89
- data/examples/demo_daemon_ctl.rb +122 -122
- data/examples/demo_services.rb +23 -23
- data/ext/win32/daemon.c +611 -596
- data/lib/win32/daemon.so +0 -0
- data/lib/win32/service.rb +1638 -1607
- data/test/test_win32_daemon.rb +58 -58
- data/test/test_win32_service.rb +409 -251
- data/test/test_win32_service_configure.rb +97 -86
- data/test/test_win32_service_create.rb +131 -103
- data/test/test_win32_service_info.rb +184 -179
- data/test/test_win32_service_status.rb +113 -111
- data/win32-service.gemspec +41 -49
- metadata +6 -6
data/examples/demo_daemon.rb
CHANGED
@@ -1,89 +1,89 @@
|
|
1
|
-
LOG_FILE = 'C:\\test.log'
|
2
|
-
|
3
|
-
begin
|
4
|
-
require 'win32/daemon'
|
5
|
-
include Win32
|
6
|
-
|
7
|
-
class DemoDaemon < Daemon
|
8
|
-
# This method fires off before the +service_main+ mainloop is entered.
|
9
|
-
# Any pre-setup code you need to run before your service's mainloop
|
10
|
-
# starts should be put here. Otherwise the service might fail with a
|
11
|
-
# timeout error when you try to start it.
|
12
|
-
#
|
13
|
-
def service_init
|
14
|
-
10.times{ |i|
|
15
|
-
File.open(LOG_FILE , 'a'){ |f| f.puts("#{i}") }
|
16
|
-
sleep 1
|
17
|
-
}
|
18
|
-
end
|
19
|
-
|
20
|
-
# This is the daemon's mainloop. In other words, whatever runs here
|
21
|
-
# is the code that runs while your service is running. Note that the
|
22
|
-
# loop is not implicit.
|
23
|
-
#
|
24
|
-
# You must setup a loop as I've done here with the 'while running?'
|
25
|
-
# code, or setup your own loop. Otherwise your service will exit and
|
26
|
-
# won't be especially useful.
|
27
|
-
#
|
28
|
-
# In this particular case, I've setup a loop to append a short message
|
29
|
-
# and timestamp to a file on your C: drive every 20 seconds. Be sure
|
30
|
-
# to stop the service when you're done!
|
31
|
-
#
|
32
|
-
def service_main(*args)
|
33
|
-
msg = 'service_main entered at: ' + Time.now.to_s
|
34
|
-
File.open(LOG_FILE, 'a'){ |f|
|
35
|
-
f.puts msg
|
36
|
-
f.puts "Args: " + args.join(',')
|
37
|
-
}
|
38
|
-
|
39
|
-
while running?
|
40
|
-
if state == RUNNING
|
41
|
-
sleep 20
|
42
|
-
msg = 'Service is running as of: ' + Time.now.to_s
|
43
|
-
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
|
44
|
-
else
|
45
|
-
sleep 0.5
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
File.open(LOG_FILE, 'a'){ |f| f.puts "STATE: #{state}" }
|
50
|
-
|
51
|
-
msg = 'service_main left at: ' + Time.now.to_s
|
52
|
-
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
|
53
|
-
end
|
54
|
-
|
55
|
-
# This event triggers when the service receives a signal to stop. I've
|
56
|
-
# added an explicit "exit!" here to ensure that the Ruby interpreter exits
|
57
|
-
# properly. I use 'exit!' instead of 'exit' because otherwise Ruby will
|
58
|
-
# raise a SystemExitError, which I don't want.
|
59
|
-
#
|
60
|
-
def service_stop
|
61
|
-
msg = 'Received stop signal at: ' + Time.now.to_s
|
62
|
-
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
|
63
|
-
exit!
|
64
|
-
end
|
65
|
-
|
66
|
-
# This event triggers when the service receives a signal to pause.
|
67
|
-
#
|
68
|
-
def service_pause
|
69
|
-
msg = 'Received pause signal at: ' + Time.now.to_s
|
70
|
-
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
|
71
|
-
end
|
72
|
-
|
73
|
-
# This event triggers when the service receives a signal to resume
|
74
|
-
# from a paused state.
|
75
|
-
#
|
76
|
-
def service_resume
|
77
|
-
msg = 'Received resume signal at: ' + Time.now.to_s
|
78
|
-
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Create an instance of the Daemon and put it into a loop. I borrowed the
|
83
|
-
# method name 'mainloop' from Tk, btw.
|
84
|
-
#
|
85
|
-
DemoDaemon.mainloop
|
86
|
-
rescue Exception => err
|
87
|
-
File.open(LOG_FILE, 'a'){ |fh| fh.puts 'Daemon failure: ' + err }
|
88
|
-
raise
|
89
|
-
end
|
1
|
+
LOG_FILE = 'C:\\test.log'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'win32/daemon'
|
5
|
+
include Win32
|
6
|
+
|
7
|
+
class DemoDaemon < Daemon
|
8
|
+
# This method fires off before the +service_main+ mainloop is entered.
|
9
|
+
# Any pre-setup code you need to run before your service's mainloop
|
10
|
+
# starts should be put here. Otherwise the service might fail with a
|
11
|
+
# timeout error when you try to start it.
|
12
|
+
#
|
13
|
+
def service_init
|
14
|
+
10.times{ |i|
|
15
|
+
File.open(LOG_FILE , 'a'){ |f| f.puts("#{i}") }
|
16
|
+
sleep 1
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
# This is the daemon's mainloop. In other words, whatever runs here
|
21
|
+
# is the code that runs while your service is running. Note that the
|
22
|
+
# loop is not implicit.
|
23
|
+
#
|
24
|
+
# You must setup a loop as I've done here with the 'while running?'
|
25
|
+
# code, or setup your own loop. Otherwise your service will exit and
|
26
|
+
# won't be especially useful.
|
27
|
+
#
|
28
|
+
# In this particular case, I've setup a loop to append a short message
|
29
|
+
# and timestamp to a file on your C: drive every 20 seconds. Be sure
|
30
|
+
# to stop the service when you're done!
|
31
|
+
#
|
32
|
+
def service_main(*args)
|
33
|
+
msg = 'service_main entered at: ' + Time.now.to_s
|
34
|
+
File.open(LOG_FILE, 'a'){ |f|
|
35
|
+
f.puts msg
|
36
|
+
f.puts "Args: " + args.join(',')
|
37
|
+
}
|
38
|
+
|
39
|
+
while running?
|
40
|
+
if state == RUNNING
|
41
|
+
sleep 20
|
42
|
+
msg = 'Service is running as of: ' + Time.now.to_s
|
43
|
+
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
|
44
|
+
else
|
45
|
+
sleep 0.5
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
File.open(LOG_FILE, 'a'){ |f| f.puts "STATE: #{state}" }
|
50
|
+
|
51
|
+
msg = 'service_main left at: ' + Time.now.to_s
|
52
|
+
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
|
53
|
+
end
|
54
|
+
|
55
|
+
# This event triggers when the service receives a signal to stop. I've
|
56
|
+
# added an explicit "exit!" here to ensure that the Ruby interpreter exits
|
57
|
+
# properly. I use 'exit!' instead of 'exit' because otherwise Ruby will
|
58
|
+
# raise a SystemExitError, which I don't want.
|
59
|
+
#
|
60
|
+
def service_stop
|
61
|
+
msg = 'Received stop signal at: ' + Time.now.to_s
|
62
|
+
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
|
63
|
+
exit!
|
64
|
+
end
|
65
|
+
|
66
|
+
# This event triggers when the service receives a signal to pause.
|
67
|
+
#
|
68
|
+
def service_pause
|
69
|
+
msg = 'Received pause signal at: ' + Time.now.to_s
|
70
|
+
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
|
71
|
+
end
|
72
|
+
|
73
|
+
# This event triggers when the service receives a signal to resume
|
74
|
+
# from a paused state.
|
75
|
+
#
|
76
|
+
def service_resume
|
77
|
+
msg = 'Received resume signal at: ' + Time.now.to_s
|
78
|
+
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Create an instance of the Daemon and put it into a loop. I borrowed the
|
83
|
+
# method name 'mainloop' from Tk, btw.
|
84
|
+
#
|
85
|
+
DemoDaemon.mainloop
|
86
|
+
rescue Exception => err
|
87
|
+
File.open(LOG_FILE, 'a'){ |fh| fh.puts 'Daemon failure: ' + err }
|
88
|
+
raise
|
89
|
+
end
|
data/examples/demo_daemon_ctl.rb
CHANGED
@@ -1,122 +1,122 @@
|
|
1
|
-
############################################################################
|
2
|
-
# demo_daemon_ctl.rb
|
3
|
-
#
|
4
|
-
# This is a command line script for installing and/or running a small
|
5
|
-
# Ruby program as a service. The service will simply write a small bit
|
6
|
-
# of text to a file every 20 seconds. It will also write some text to the
|
7
|
-
# file during the initialization (service_init) step.
|
8
|
-
#
|
9
|
-
# It should take about 10 seconds to start, which is intentional - it's a test
|
10
|
-
# of the service_init hook, so don't be surprised if you see "one moment,
|
11
|
-
# start pending" about 10 times on the command line.
|
12
|
-
#
|
13
|
-
# The file in question is C:\test.log. Feel free to delete it when finished.
|
14
|
-
#
|
15
|
-
# To run the service, you must install it first.
|
16
|
-
#
|
17
|
-
# Usage: ruby demo_daemon_ctl.rb <option>
|
18
|
-
#
|
19
|
-
# Note that you *must* pass this program an option
|
20
|
-
#
|
21
|
-
# Options:
|
22
|
-
# install - Installs the service. The service name is "DemoSvc"
|
23
|
-
# and the display name is "Demo".
|
24
|
-
# start - Starts the service. Make sure you stop it at some point or
|
25
|
-
# you will eventually fill up your filesystem!.
|
26
|
-
# stop - Stops the service.
|
27
|
-
# pause - Pauses the service.
|
28
|
-
# resume - Resumes the service.
|
29
|
-
# uninstall - Uninstalls the service.
|
30
|
-
# delete - Same as uninstall.
|
31
|
-
#
|
32
|
-
# You can also used the Windows Services GUI to start and stop the service.
|
33
|
-
#
|
34
|
-
# To get to the Windows Services GUI just follow:
|
35
|
-
# Start -> Control Panel -> Administrative Tools -> Services
|
36
|
-
############################################################################
|
37
|
-
require 'win32/service'
|
38
|
-
require 'rbconfig'
|
39
|
-
include Win32
|
40
|
-
include Config
|
41
|
-
|
42
|
-
# Make sure you're using the version you think you're using.
|
43
|
-
puts 'VERSION: ' + Service::VERSION
|
44
|
-
|
45
|
-
SERVICE_NAME = 'DemoSvc'
|
46
|
-
SERVICE_DISPLAYNAME = 'Demo'
|
47
|
-
|
48
|
-
# Quote the full path to deal with possible spaces in the path name.
|
49
|
-
ruby = File.join(CONFIG['bindir'], 'ruby').tr('/', '\\')
|
50
|
-
path = ' "' + File.dirname(File.expand_path($0)).tr('/', '\\')
|
51
|
-
path += '\demo_daemon.rb"'
|
52
|
-
cmd = ruby + path
|
53
|
-
|
54
|
-
# You must provide at least one argument.
|
55
|
-
raise ArgumentError, 'No argument provided' unless ARGV[0]
|
56
|
-
|
57
|
-
case ARGV[0].downcase
|
58
|
-
when 'install'
|
59
|
-
Service.new(
|
60
|
-
:service_name => SERVICE_NAME,
|
61
|
-
:display_name => SERVICE_DISPLAYNAME,
|
62
|
-
:description => 'Sample Ruby service',
|
63
|
-
:binary_path_name => cmd
|
64
|
-
)
|
65
|
-
puts 'Service ' + SERVICE_NAME + ' installed'
|
66
|
-
when 'start'
|
67
|
-
if Service.status(SERVICE_NAME).current_state != 'running'
|
68
|
-
Service.start(SERVICE_NAME, nil, 'hello', 'world')
|
69
|
-
while Service.status(SERVICE_NAME).current_state != 'running'
|
70
|
-
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
|
71
|
-
sleep 1
|
72
|
-
end
|
73
|
-
puts 'Service ' + SERVICE_NAME + ' started'
|
74
|
-
else
|
75
|
-
puts 'Already running'
|
76
|
-
end
|
77
|
-
when 'stop'
|
78
|
-
if Service.status(SERVICE_NAME).current_state != 'stopped'
|
79
|
-
Service.stop(SERVICE_NAME)
|
80
|
-
while Service.status(SERVICE_NAME).current_state != 'stopped'
|
81
|
-
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
|
82
|
-
sleep 1
|
83
|
-
end
|
84
|
-
puts 'Service ' + SERVICE_NAME + ' stopped'
|
85
|
-
else
|
86
|
-
puts 'Already stopped'
|
87
|
-
end
|
88
|
-
when 'uninstall', 'delete'
|
89
|
-
if Service.status(SERVICE_NAME).current_state != 'stopped'
|
90
|
-
Service.stop(SERVICE_NAME)
|
91
|
-
end
|
92
|
-
while Service.status(SERVICE_NAME).current_state != 'stopped'
|
93
|
-
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
|
94
|
-
sleep 1
|
95
|
-
end
|
96
|
-
Service.delete(SERVICE_NAME)
|
97
|
-
puts 'Service ' + SERVICE_NAME + ' deleted'
|
98
|
-
when 'pause'
|
99
|
-
if Service.status(SERVICE_NAME).current_state != 'paused'
|
100
|
-
Service.pause(SERVICE_NAME)
|
101
|
-
while Service.status(SERVICE_NAME).current_state != 'paused'
|
102
|
-
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
|
103
|
-
sleep 1
|
104
|
-
end
|
105
|
-
puts 'Service ' + SERVICE_NAME + ' paused'
|
106
|
-
else
|
107
|
-
puts 'Already paused'
|
108
|
-
end
|
109
|
-
when 'resume'
|
110
|
-
if Service.status(SERVICE_NAME).current_state != 'running'
|
111
|
-
Service.resume(SERVICE_NAME)
|
112
|
-
while Service.status(SERVICE_NAME).current_state != 'running'
|
113
|
-
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
|
114
|
-
sleep 1
|
115
|
-
end
|
116
|
-
puts 'Service ' + SERVICE_NAME + ' resumed'
|
117
|
-
else
|
118
|
-
puts 'Already running'
|
119
|
-
end
|
120
|
-
else
|
121
|
-
raise ArgumentError, 'unknown option: ' + ARGV[0]
|
122
|
-
end
|
1
|
+
############################################################################
|
2
|
+
# demo_daemon_ctl.rb
|
3
|
+
#
|
4
|
+
# This is a command line script for installing and/or running a small
|
5
|
+
# Ruby program as a service. The service will simply write a small bit
|
6
|
+
# of text to a file every 20 seconds. It will also write some text to the
|
7
|
+
# file during the initialization (service_init) step.
|
8
|
+
#
|
9
|
+
# It should take about 10 seconds to start, which is intentional - it's a test
|
10
|
+
# of the service_init hook, so don't be surprised if you see "one moment,
|
11
|
+
# start pending" about 10 times on the command line.
|
12
|
+
#
|
13
|
+
# The file in question is C:\test.log. Feel free to delete it when finished.
|
14
|
+
#
|
15
|
+
# To run the service, you must install it first.
|
16
|
+
#
|
17
|
+
# Usage: ruby demo_daemon_ctl.rb <option>
|
18
|
+
#
|
19
|
+
# Note that you *must* pass this program an option
|
20
|
+
#
|
21
|
+
# Options:
|
22
|
+
# install - Installs the service. The service name is "DemoSvc"
|
23
|
+
# and the display name is "Demo".
|
24
|
+
# start - Starts the service. Make sure you stop it at some point or
|
25
|
+
# you will eventually fill up your filesystem!.
|
26
|
+
# stop - Stops the service.
|
27
|
+
# pause - Pauses the service.
|
28
|
+
# resume - Resumes the service.
|
29
|
+
# uninstall - Uninstalls the service.
|
30
|
+
# delete - Same as uninstall.
|
31
|
+
#
|
32
|
+
# You can also used the Windows Services GUI to start and stop the service.
|
33
|
+
#
|
34
|
+
# To get to the Windows Services GUI just follow:
|
35
|
+
# Start -> Control Panel -> Administrative Tools -> Services
|
36
|
+
############################################################################
|
37
|
+
require 'win32/service'
|
38
|
+
require 'rbconfig'
|
39
|
+
include Win32
|
40
|
+
include Config
|
41
|
+
|
42
|
+
# Make sure you're using the version you think you're using.
|
43
|
+
puts 'VERSION: ' + Service::VERSION
|
44
|
+
|
45
|
+
SERVICE_NAME = 'DemoSvc'
|
46
|
+
SERVICE_DISPLAYNAME = 'Demo'
|
47
|
+
|
48
|
+
# Quote the full path to deal with possible spaces in the path name.
|
49
|
+
ruby = File.join(CONFIG['bindir'], 'ruby').tr('/', '\\')
|
50
|
+
path = ' "' + File.dirname(File.expand_path($0)).tr('/', '\\')
|
51
|
+
path += '\demo_daemon.rb"'
|
52
|
+
cmd = ruby + path
|
53
|
+
|
54
|
+
# You must provide at least one argument.
|
55
|
+
raise ArgumentError, 'No argument provided' unless ARGV[0]
|
56
|
+
|
57
|
+
case ARGV[0].downcase
|
58
|
+
when 'install'
|
59
|
+
Service.new(
|
60
|
+
:service_name => SERVICE_NAME,
|
61
|
+
:display_name => SERVICE_DISPLAYNAME,
|
62
|
+
:description => 'Sample Ruby service',
|
63
|
+
:binary_path_name => cmd
|
64
|
+
)
|
65
|
+
puts 'Service ' + SERVICE_NAME + ' installed'
|
66
|
+
when 'start'
|
67
|
+
if Service.status(SERVICE_NAME).current_state != 'running'
|
68
|
+
Service.start(SERVICE_NAME, nil, 'hello', 'world')
|
69
|
+
while Service.status(SERVICE_NAME).current_state != 'running'
|
70
|
+
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
|
71
|
+
sleep 1
|
72
|
+
end
|
73
|
+
puts 'Service ' + SERVICE_NAME + ' started'
|
74
|
+
else
|
75
|
+
puts 'Already running'
|
76
|
+
end
|
77
|
+
when 'stop'
|
78
|
+
if Service.status(SERVICE_NAME).current_state != 'stopped'
|
79
|
+
Service.stop(SERVICE_NAME)
|
80
|
+
while Service.status(SERVICE_NAME).current_state != 'stopped'
|
81
|
+
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
|
82
|
+
sleep 1
|
83
|
+
end
|
84
|
+
puts 'Service ' + SERVICE_NAME + ' stopped'
|
85
|
+
else
|
86
|
+
puts 'Already stopped'
|
87
|
+
end
|
88
|
+
when 'uninstall', 'delete'
|
89
|
+
if Service.status(SERVICE_NAME).current_state != 'stopped'
|
90
|
+
Service.stop(SERVICE_NAME)
|
91
|
+
end
|
92
|
+
while Service.status(SERVICE_NAME).current_state != 'stopped'
|
93
|
+
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
|
94
|
+
sleep 1
|
95
|
+
end
|
96
|
+
Service.delete(SERVICE_NAME)
|
97
|
+
puts 'Service ' + SERVICE_NAME + ' deleted'
|
98
|
+
when 'pause'
|
99
|
+
if Service.status(SERVICE_NAME).current_state != 'paused'
|
100
|
+
Service.pause(SERVICE_NAME)
|
101
|
+
while Service.status(SERVICE_NAME).current_state != 'paused'
|
102
|
+
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
|
103
|
+
sleep 1
|
104
|
+
end
|
105
|
+
puts 'Service ' + SERVICE_NAME + ' paused'
|
106
|
+
else
|
107
|
+
puts 'Already paused'
|
108
|
+
end
|
109
|
+
when 'resume'
|
110
|
+
if Service.status(SERVICE_NAME).current_state != 'running'
|
111
|
+
Service.resume(SERVICE_NAME)
|
112
|
+
while Service.status(SERVICE_NAME).current_state != 'running'
|
113
|
+
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
|
114
|
+
sleep 1
|
115
|
+
end
|
116
|
+
puts 'Service ' + SERVICE_NAME + ' resumed'
|
117
|
+
else
|
118
|
+
puts 'Already running'
|
119
|
+
end
|
120
|
+
else
|
121
|
+
raise ArgumentError, 'unknown option: ' + ARGV[0]
|
122
|
+
end
|
data/examples/demo_services.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
|
-
#######################################################################
|
2
|
-
# demo_services.rb
|
3
|
-
#
|
4
|
-
# Test script for general futzing that shows off the basic
|
5
|
-
# capabilities of this library. Modify as you see fit.
|
6
|
-
#######################################################################
|
7
|
-
require 'win32/service'
|
8
|
-
include Win32
|
9
|
-
|
10
|
-
puts "VERSION: " + Service::VERSION
|
11
|
-
|
12
|
-
p Service.exists?("ClipSrv")
|
13
|
-
p Service.exists?("foo")
|
14
|
-
|
15
|
-
status = Service.status("ClipSrv")
|
16
|
-
p status
|
17
|
-
|
18
|
-
info = Service.config_info("ClipSrv")
|
19
|
-
p info
|
20
|
-
|
21
|
-
Service.services{ |struct|
|
22
|
-
p struct
|
23
|
-
}
|
1
|
+
#######################################################################
|
2
|
+
# demo_services.rb
|
3
|
+
#
|
4
|
+
# Test script for general futzing that shows off the basic
|
5
|
+
# capabilities of this library. Modify as you see fit.
|
6
|
+
#######################################################################
|
7
|
+
require 'win32/service'
|
8
|
+
include Win32
|
9
|
+
|
10
|
+
puts "VERSION: " + Service::VERSION
|
11
|
+
|
12
|
+
p Service.exists?("ClipSrv")
|
13
|
+
p Service.exists?("foo")
|
14
|
+
|
15
|
+
status = Service.status("ClipSrv")
|
16
|
+
p status
|
17
|
+
|
18
|
+
info = Service.config_info("ClipSrv")
|
19
|
+
p info
|
20
|
+
|
21
|
+
Service.services{ |struct|
|
22
|
+
p struct
|
23
|
+
}
|