win32-service 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGES CHANGED
@@ -1,3 +1,24 @@
1
+ == 0.7.0 - 30-Jun-2009
2
+ * INTERFACE CHANGE: The Service.new and Service.configure methods now accept
3
+ a single hash argument only. The :service_name key is mandatory, while the
4
+ :host key is optional.
5
+ * Fixed a bug in the Service.services method where a segfault would occur if
6
+ the binary_path_name was greater than 260 characters. The buffer size has
7
+ been increased to 1024 characters. Thanks go to Dan Daniels for the spot.
8
+ * Altered the Daemon class so that the Ruby interpreter was not invoked within
9
+ the Service_Main function. The functions that close stdin, stdout and stderr
10
+ are now called within the mainloop method. Thanks go to Tim Hanson for the
11
+ spot and the patch.
12
+ * Eliminated a minor build warning in daemon.c
13
+ * License changed to Artistic 2.0, with corresponding gemspec update.
14
+ * Added an uninstall rake task.
15
+ * Updated the service_stop method in the demo_daemon.rb file, and added some
16
+ additional comments.
17
+ * The test files were renamed.
18
+ * Several tests were updated and refactored to use Test::Unit 2.x. That
19
+ library is now a dependency.
20
+ * The 'uninstall' Rakefile task is now more verbose.
21
+
1
22
  == 0.6.1 - 1-Jan-2008
2
23
  * The Service.services method now handles the scenario where a particular
3
24
  service may still exist, but its underlying registry entry has been deleted.
data/MANIFEST CHANGED
@@ -11,8 +11,9 @@
11
11
  * examples/demo_daemon_ctl.rb
12
12
  * examples/demo_services.rb
13
13
  * lib/win32/service.rb
14
- * test/tc_daemon.rb
15
- * test/tc_service_create.rb
16
- * test/tc_service_info.rb
17
- * test/tc_service_status.rb
18
- * test/tc_service.rb
14
+ * test/test_win32_daemon.rb
15
+ * test/test_win32_service_configure.rb
16
+ * test/test_win32_service_create.rb
17
+ * test/test_win32_service_info.rb
18
+ * test/test_win32_service_status.rb
19
+ * test/test_win32_service.rb
data/README CHANGED
@@ -41,4 +41,5 @@ will happen if your W32Time service isn't running.
41
41
 
42
42
  = Future Plans
43
43
  * Pure Ruby Daemon class
44
- * Add service_session_change hook
44
+ * Add service_session_change hook
45
+ * Add a WMI variant of the Service class.
data/Rakefile ADDED
@@ -0,0 +1,128 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+ require 'rake/testtask'
4
+ require 'rbconfig'
5
+ include Config
6
+
7
+ desc "Cleans up the C related files created during the build"
8
+ task :clean do
9
+ Dir.chdir('ext') do
10
+ if File.exists?('daemon.o') || File.exists?('daemon.so')
11
+ sh 'nmake distclean'
12
+ end
13
+ File.delete('win32/daemon.so') if File.exists?('win32/daemon.so')
14
+ end
15
+ end
16
+
17
+ desc "Builds, but does not install, the win32-service library"
18
+ task :build => [:clean] do
19
+ Dir.chdir('ext') do
20
+ ruby 'extconf.rb'
21
+ sh 'nmake'
22
+ FileUtils.cp('daemon.so', 'win32/daemon.so')
23
+ end
24
+ end
25
+
26
+ desc "Install the win32-service library (non-gem)"
27
+ task :install => [:build] do
28
+ Dir.chdir('ext') do
29
+ sh 'nmake install'
30
+ end
31
+ install_dir = File.join(CONFIG['sitelibdir'], 'win32')
32
+ Dir.mkdir(install_dir) unless File.exists?(install_dir)
33
+ FileUtils.cp('lib/win32/service.rb', install_dir, :verbose => true)
34
+ end
35
+
36
+ desc 'Install the win32-service library as a gem'
37
+ task :install_gem => [:clean] do
38
+ ruby 'win32-service.gemspec'
39
+ file = Dir['win32-service*.gem'].first
40
+ sh "gem install #{file}"
41
+ end
42
+
43
+ desc 'Uninstall the (non-gem) win32-service library.'
44
+ task :uninstall do
45
+ service = File.join(CONFIG['sitelibdir'], 'win32', 'service.rb')
46
+ FileUtils.rm(service, :verbose => true) if File.exists?(service)
47
+
48
+ daemon = File.join(CONFIG['sitearchdir'], 'win32', 'daemon.so')
49
+ FileUtils.rm(daemon, :verbose => true) if File.exists?(daemon)
50
+ end
51
+
52
+ desc "Build a binary gem"
53
+ task :build_binary_gem => [:build] do
54
+ if File.exists?('lib/win32/daemon.rb')
55
+ mv 'lib/win32/daemon.rb', 'lib/win32/daemon.orig'
56
+ end
57
+
58
+ cp 'ext/win32/daemon.so', 'lib/win32/daemon.so'
59
+
60
+ task :build_binary_gem => [:clean]
61
+
62
+ spec = Gem::Specification.new do |gem|
63
+ gem.name = 'win32-service'
64
+ gem.version = '0.7.0'
65
+ gem.authors = ['Daniel J. Berger', 'Park Heesob']
66
+ gem.email = 'djberg96@gmail.com'
67
+ gem.license = 'Artistic 2.0'
68
+ gem.homepage = 'http://www.rubyforge.org/projects/win32utils'
69
+ gem.platform = Gem::Platform::CURRENT
70
+ gem.summary = 'An interface for MS Windows services'
71
+ gem.test_files = Dir['test/test*.rb']
72
+ gem.has_rdoc = true
73
+ gem.files = Dir['**/*'].delete_if{ |f|
74
+ f.include?('CVS') || f.include?('ext') || f.include?('daemon.orig')
75
+ }
76
+
77
+ gem.extra_rdoc_files = [
78
+ 'CHANGES',
79
+ 'README',
80
+ 'MANIFEST',
81
+ 'doc/service.txt',
82
+ 'doc/daemon.txt',
83
+ 'ext/win32/daemon.c'
84
+ ]
85
+
86
+ gem.rubyforge_project = 'win32utils'
87
+ gem.required_ruby_version = '>= 1.8.2'
88
+
89
+ gem.add_dependency('windows-pr', '>= 1.0.5')
90
+ gem.add_dependency('test-unit', '>= 2.0.2')
91
+
92
+ gem.description = <<-EOF
93
+ The win32-service library provides a Ruby interface to services on
94
+ MS Windows. You can create new services, or control, configure and
95
+ inspect existing services.
96
+
97
+ In addition, you can create a pure Ruby service by using the Daemon
98
+ class that is included as part of the library.
99
+ EOF
100
+ end
101
+
102
+ Gem::Builder.new(spec).build
103
+ end
104
+
105
+ desc "Run the test suite for the win32-service library"
106
+ Rake::TestTask.new do |t|
107
+ task :test => :build
108
+ t.libs << 'ext'
109
+ t.verbose = true
110
+ t.warning = true
111
+ end
112
+
113
+ desc "Run the test suite for the Win32::Daemon class (only)"
114
+ Rake::TestTask.new('test_daemon') do |t|
115
+ task :test_daemon => :build
116
+ t.libs << 'ext'
117
+ t.verbose = true
118
+ t.warning = true
119
+ t.test_files = FileList['test/test_win32_daemon.rb']
120
+ end
121
+
122
+ task :test do
123
+ Rake.application[:clean].execute
124
+ end
125
+
126
+ task :test_daemon do
127
+ Rake.application[:clean].execute
128
+ end
data/doc/daemon.txt CHANGED
@@ -7,7 +7,7 @@
7
7
  def service_main
8
8
  while running?
9
9
  sleep 3
10
- File.open("c:\\test.log","a+"){ |f| f.puts "service is running" }
10
+ File.open("c:\\test.log", "a"){ |f| f.puts "service is running" }
11
11
  end
12
12
  end
13
13
  end
@@ -131,6 +131,8 @@ Daemon::IDLE
131
131
  http://rubyforge.org/projects/win32utils.
132
132
 
133
133
  = Future Plans
134
+ Rewrite the Daemon class in pure Ruby.
135
+
134
136
  Suggestions welcome. Please log them on the Feature Request tracker at
135
137
  http://rubyforge.org/projects/win32utils
136
138
 
@@ -140,10 +142,10 @@ Daemon::IDLE
140
142
  service responsiveness issues.
141
143
 
142
144
  = Copyright
143
- (C) 2003-2008 Daniel J. Berger, All Rights Reserved
145
+ (C) 2003-2009 Daniel J. Berger, All Rights Reserved
144
146
 
145
147
  = License
146
- Ruby's
148
+ Artistic 2.0
147
149
 
148
150
  = Warranty
149
151
  This package is provided "as is" and without any express or
data/doc/service.txt CHANGED
@@ -17,7 +17,8 @@
17
17
  include Win32
18
18
 
19
19
  # Create a new service
20
- Service.create('some_service', nil,
20
+ Service.create(
21
+ :service_name => 'some_service',
21
22
  :service_type => Service::WIN32_OWN_PROCESS,
22
23
  :description => 'A custom service I wrote just for fun'
23
24
  :start_type => Service::AUTO_START,
@@ -52,11 +53,12 @@
52
53
  }
53
54
 
54
55
  = Class Methods
55
- Service.new(service_name, host=nil, options={})
56
- Creates a new service with +service_name+ on +host+, or the local host
57
- if no host is specified. The +options+ parameter is a hash that can
56
+ Service.new(options={})
57
+ Creates a new service. The +options+ parameter is a hash that can
58
58
  contain any of the following parameters, and their default values:
59
59
 
60
+ * service_name => nil (mandatory)
61
+ * host => nil
60
62
  * display_name => service_name
61
63
  * desired_access => Service::ALL_ACCESS
62
64
  * service_type => Service::WIN32_OWN_PROCESS | Service::INTERACTIVE_PROCESS
@@ -69,11 +71,12 @@ Service.new(service_name, host=nil, options={})
69
71
  * password => nil
70
72
  * description => nil
71
73
 
72
- Service.configure(service_name, host=nil, options={})
73
- Configures the named +service_name+ on +host+, or the local host if no
74
- host is specified. The +options+ parameter is a hash that can contain any
75
- of the following parameters:
74
+ Service.configure(options={})
75
+ Configures an existing service. The +options+ parameter is a hash that can
76
+ contain any of the following parameters:
76
77
 
78
+ * service_name (mandatory)
79
+ * host
77
80
  * service_type
78
81
  * start_type
79
82
  * error_control
@@ -350,10 +353,10 @@ Service::ERROR_CRITICAL
350
353
  Use RegisterServiceCtrlHandlerEx().
351
354
 
352
355
  = Copyright
353
- (C) 2003-2008, Daniel J. Berger, All Rights Reserved
356
+ (C) 2003-2009, Daniel J. Berger, All Rights Reserved
354
357
 
355
358
  = License
356
- Ruby's
359
+ Artistic 2.0
357
360
 
358
361
  = Warranty
359
362
  This package is provided "as is" and without any express or
@@ -0,0 +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
@@ -0,0 +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
+ }
data/ext/extconf.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'mkmf'
2
-
3
- dir_config('win32-daemon')
4
- have_func('RegisterServiceCtrlHandlerEx')
5
- create_makefile('win32/daemon', 'win32')
1
+ require 'mkmf'
2
+
3
+ dir_config('win32-daemon')
4
+ have_func('RegisterServiceCtrlHandlerEx')
5
+ create_makefile('win32/daemon', 'win32')
data/ext/win32/daemon.c CHANGED
@@ -5,7 +5,7 @@
5
5
  #include <malloc.h>
6
6
  #include <tchar.h>
7
7
 
8
- #define WIN32_SERVICE_VERSION "0.6.1"
8
+ #define WIN32_SERVICE_VERSION "0.7.0"
9
9
 
10
10
  static VALUE cDaemonError;
11
11
 
@@ -66,34 +66,23 @@ void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv)
66
66
  {
67
67
  // Obtain the name of the service.
68
68
  LPTSTR lpszServiceName = lpszArgv[0];
69
-
69
+
70
70
  // Args passed to Service.start
71
71
  if(dwArgc > 1){
72
- int i;
72
+ unsigned int i;
73
73
  Argc = dwArgc - 1;
74
74
  Argv = malloc(sizeof(VALUE)*Argc);
75
-
76
- for(i=1;i<dwArgc;i++)
75
+
76
+ for(i=1; i < dwArgc; i++)
77
77
  Argv[i-1] = rb_str_new2(lpszArgv[i]);
78
78
  }
79
79
 
80
80
  // Register the service ctrl handler.
81
81
  ssh = RegisterServiceCtrlHandler(lpszServiceName,
82
82
  (LPHANDLER_FUNCTION)Service_Ctrl);
83
-
84
- // Redirect STDIN, STDOUT and STDERR to the NUL device if they're still
85
- // associated with a tty. This helps newbs avoid Errno::EBADF errors.
86
- if(rb_funcall(rb_stdin, rb_intern("isatty"), 0) == Qtrue)
87
- rb_funcall(rb_stdin, rb_intern("reopen"), 1, rb_str_new2("NUL"));
88
-
89
- if(rb_funcall(rb_stdout, rb_intern("isatty"), 0) == Qtrue)
90
- rb_funcall(rb_stdout, rb_intern("reopen"), 1, rb_str_new2("NUL"));
91
-
92
- if(rb_funcall(rb_stderr, rb_intern("isatty"), 0) == Qtrue)
93
- rb_funcall(rb_stderr, rb_intern("reopen"), 1, rb_str_new2("NUL"));
94
83
 
95
84
  // no service to stop, no service handle to notify, nothing to do but exit
96
- if(ssh == (SERVICE_STATUS_HANDLE)0)
85
+ if(ssh == (SERVICE_STATUS_HANDLE)0)
97
86
  return;
98
87
 
99
88
  // The service has started.
@@ -274,7 +263,7 @@ DWORD WINAPI ThreadProc(LPVOID lpParameter){
274
263
  SERVICE_TABLE_ENTRY ste[] =
275
264
  {{TEXT(""),(LPSERVICE_MAIN_FUNCTION)Service_Main}, {NULL, NULL}};
276
265
 
277
- // No service to step, no service handle, no ruby exceptions, just
266
+ // No service to step, no service handle, no ruby exceptions, just
278
267
  // terminate the thread.
279
268
  if(!StartServiceCtrlDispatcher(ste))
280
269
  return 1;
@@ -291,12 +280,12 @@ static VALUE daemon_allocate(VALUE klass){
291
280
  static VALUE daemon_mainloop_protect(VALUE self)
292
281
  {
293
282
  if(rb_respond_to(self,rb_intern("service_main"))){
294
- if(Argc == 0)
283
+ if(Argc == 0)
295
284
  rb_funcall(self, rb_intern("service_main"), 0);
296
285
  else
297
286
  rb_funcall2(self, rb_intern("service_main"), Argc, Argv);
298
- }
299
-
287
+ }
288
+
300
289
  return self;
301
290
  }
302
291
 
@@ -341,115 +330,126 @@ static VALUE daemon_mainloop_ensure(VALUE self)
341
330
  */
342
331
  static VALUE daemon_mainloop(VALUE self)
343
332
  {
344
- DWORD ThreadId;
345
- HANDLE events[2];
346
- DWORD index;
347
- VALUE result, EventHookHash;
348
- int status = 0;
333
+ DWORD ThreadId;
334
+ HANDLE events[2];
335
+ DWORD index;
336
+ VALUE result, EventHookHash;
337
+ int status = 0;
338
+
339
+ dwServiceState = 0;
340
+
341
+ // Redirect STDIN, STDOUT and STDERR to the NUL device if they're still
342
+ // associated with a tty. This helps newbs avoid Errno::EBADF errors.
343
+ if(rb_funcall(rb_stdin, rb_intern("isatty"), 0) == Qtrue)
344
+ rb_funcall(rb_stdin, rb_intern("reopen"), 1, rb_str_new2("NUL"));
349
345
 
350
- dwServiceState = 0;
346
+ if(rb_funcall(rb_stdout, rb_intern("isatty"), 0) == Qtrue)
347
+ rb_funcall(rb_stdout, rb_intern("reopen"), 1, rb_str_new2("NUL"));
351
348
 
352
- // use a markable instance variable to prevent the garbage collector
349
+ if(rb_funcall(rb_stderr, rb_intern("isatty"), 0) == Qtrue)
350
+ rb_funcall(rb_stderr, rb_intern("reopen"), 1, rb_str_new2("NUL"));
351
+
352
+ // Use a markable instance variable to prevent the garbage collector
353
353
  // from freeing the hash before Ruby_Service_Ctrl exits, or just
354
354
  // at any ole time while running the service
355
355
  EventHookHash = rb_hash_new();
356
356
  rb_ivar_set(self, rb_intern("@event_hooks"), EventHookHash);
357
357
 
358
- // Event hooks
359
- if(rb_respond_to(self, rb_intern("service_stop"))){
360
- rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_STOP),
361
- rb_ary_new3(2, self, INT2NUM(rb_intern("service_stop"))));
362
- }
358
+ // Event hooks
359
+ if(rb_respond_to(self, rb_intern("service_stop"))){
360
+ rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_STOP),
361
+ rb_ary_new3(2, self, INT2NUM(rb_intern("service_stop"))));
362
+ }
363
363
 
364
- if(rb_respond_to(self, rb_intern("service_pause"))){
365
- rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_PAUSE),
366
- rb_ary_new3(2, self, INT2NUM(rb_intern("service_pause"))));
367
- }
364
+ if(rb_respond_to(self, rb_intern("service_pause"))){
365
+ rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_PAUSE),
366
+ rb_ary_new3(2, self, INT2NUM(rb_intern("service_pause"))));
367
+ }
368
368
 
369
- if(rb_respond_to(self, rb_intern("service_resume"))){
370
- rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_CONTINUE),
371
- rb_ary_new3(2, self, INT2NUM(rb_intern("service_resume"))));
372
- }
369
+ if(rb_respond_to(self, rb_intern("service_resume"))){
370
+ rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_CONTINUE),
371
+ rb_ary_new3(2, self, INT2NUM(rb_intern("service_resume"))));
372
+ }
373
373
 
374
- if(rb_respond_to(self, rb_intern("service_interrogate"))){
375
- rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_INTERROGATE),
376
- rb_ary_new3(2, self, INT2NUM(rb_intern("service_interrogate"))));
377
- }
374
+ if(rb_respond_to(self, rb_intern("service_interrogate"))){
375
+ rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_INTERROGATE),
376
+ rb_ary_new3(2, self, INT2NUM(rb_intern("service_interrogate"))));
377
+ }
378
378
 
379
- if(rb_respond_to(self, rb_intern("service_shutdown"))){
380
- rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_SHUTDOWN),
381
- rb_ary_new3(2, self, INT2NUM(rb_intern("service_shutdown"))));
382
- }
379
+ if(rb_respond_to(self, rb_intern("service_shutdown"))){
380
+ rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_SHUTDOWN),
381
+ rb_ary_new3(2, self, INT2NUM(rb_intern("service_shutdown"))));
382
+ }
383
383
 
384
384
  #ifdef SERVICE_CONTROL_PARAMCHANGE
385
- if(rb_respond_to(self, rb_intern("service_paramchange"))){
386
- rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_PARAMCHANGE),
387
- rb_ary_new3(2, self, INT2NUM(rb_intern("service_paramchange"))));
388
- }
385
+ if(rb_respond_to(self, rb_intern("service_paramchange"))){
386
+ rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_PARAMCHANGE),
387
+ rb_ary_new3(2, self, INT2NUM(rb_intern("service_paramchange"))));
388
+ }
389
389
  #endif
390
390
 
391
391
  #ifdef SERVICE_CONTROL_NETBINDADD
392
- if(rb_respond_to(self, rb_intern("service_netbindadd"))){
393
- rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDADD),
394
- rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbindadd"))));
395
- }
392
+ if(rb_respond_to(self, rb_intern("service_netbindadd"))){
393
+ rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDADD),
394
+ rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbindadd"))));
395
+ }
396
396
  #endif
397
397
 
398
398
  #ifdef SERVICE_CONTROL_NETBINDREMOVE
399
- if(rb_respond_to(self, rb_intern("service_netbindremove"))){
400
- rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDREMOVE),
401
- rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbindremove"))));
402
- }
399
+ if(rb_respond_to(self, rb_intern("service_netbindremove"))){
400
+ rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDREMOVE),
401
+ rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbindremove"))));
402
+ }
403
403
  #endif
404
404
 
405
405
  #ifdef SERVICE_CONTROL_NETBINDENABLE
406
- if(rb_respond_to(self, rb_intern("service_netbindenable"))){
407
- rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDENABLE),
408
- rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbindenable"))));
409
- }
406
+ if(rb_respond_to(self, rb_intern("service_netbindenable"))){
407
+ rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDENABLE),
408
+ rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbindenable"))));
409
+ }
410
410
  #endif
411
411
 
412
412
  #ifdef SERVICE_CONTROL_NETBINDDISABLE
413
- if(rb_respond_to(self, rb_intern("service_netbinddisable"))){
414
- rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDDISABLE),
415
- rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbinddisable"))));
416
- }
413
+ if(rb_respond_to(self, rb_intern("service_netbinddisable"))){
414
+ rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDDISABLE),
415
+ rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbinddisable"))));
416
+ }
417
417
  #endif
418
418
 
419
- // calling init here so that init failures never even tries to
420
- // start the service... of course that means that init methods
421
- // must be very quick, because the SCM will be receiving no
422
- // START_PENDING messages while init's running - I may fix this
423
- // later
424
- if(rb_respond_to(self, rb_intern("service_init")))
425
- rb_funcall(self, rb_intern("service_init"),0);
419
+ // Calling init here so that init failures never even tries to
420
+ // start the service... of course that means that init methods
421
+ // must be very quick, because the SCM will be receiving no
422
+ // START_PENDING messages while init's running - I may fix this
423
+ // later
424
+ if(rb_respond_to(self, rb_intern("service_init")))
425
+ rb_funcall(self, rb_intern("service_init"),0);
426
426
 
427
- // Create the event to signal the service to start.
428
- hStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
427
+ // Create the event to signal the service to start.
428
+ hStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
429
429
 
430
- if(hStartEvent == NULL)
431
- rb_raise(cDaemonError, ErrorDescription(GetLastError()));
430
+ if(hStartEvent == NULL)
431
+ rb_raise(cDaemonError, ErrorDescription(GetLastError()));
432
432
 
433
- // Create the event to signal the service to stop.
434
- hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
433
+ // Create the event to signal the service to stop.
434
+ hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
435
435
 
436
- if(hStopEvent == NULL)
437
- rb_raise(cDaemonError, ErrorDescription(GetLastError()));
436
+ if(hStopEvent == NULL)
437
+ rb_raise(cDaemonError, ErrorDescription(GetLastError()));
438
438
 
439
- // Create the event to signal the service that stop has completed
440
- hStopCompletedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
439
+ // Create the event to signal the service that stop has completed
440
+ hStopCompletedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
441
441
 
442
- if(hStopCompletedEvent == NULL)
443
- rb_raise(cDaemonError, ErrorDescription(GetLastError()));
442
+ if(hStopCompletedEvent == NULL)
443
+ rb_raise(cDaemonError, ErrorDescription(GetLastError()));
444
444
 
445
- // Create Thread for service main
446
- hThread = CreateThread(NULL, 0, ThreadProc, 0, 0, &ThreadId);
445
+ // Create Thread for service main
446
+ hThread = CreateThread(NULL, 0, ThreadProc, 0, 0, &ThreadId);
447
447
 
448
- if(hThread == INVALID_HANDLE_VALUE)
449
- rb_raise(cDaemonError, ErrorDescription(GetLastError()));
448
+ if(hThread == INVALID_HANDLE_VALUE)
449
+ rb_raise(cDaemonError, ErrorDescription(GetLastError()));
450
450
 
451
- events[0] = hThread;
452
- events[1] = hStartEvent;
451
+ events[0] = hThread;
452
+ events[1] = hStartEvent;
453
453
 
454
454
  // wait for Service_Main function to either start the service OR terminate
455
455
  while((index = WaitForMultipleObjects(2,events,FALSE,1000)) == WAIT_TIMEOUT)
@@ -480,10 +480,10 @@ static VALUE daemon_mainloop(VALUE self)
480
480
  /*
481
481
  * Returns the state of the service (as an constant integer) which can be any
482
482
  * of the service status constants, e.g. RUNNING, PAUSED, etc.
483
- *
483
+ *
484
484
  * This method is typically used within your service_main method to setup the
485
485
  * loop. For example:
486
- *
486
+ *
487
487
  * class MyDaemon < Daemon
488
488
  * def service_main
489
489
  * while state == RUNNING || state == PAUSED || state == IDLE
@@ -491,7 +491,7 @@ static VALUE daemon_mainloop(VALUE self)
491
491
  * end
492
492
  * end
493
493
  * end
494
- *
494
+ *
495
495
  * See the Daemon#running? method for an abstraction of the above code.
496
496
  */
497
497
  static VALUE daemon_state(VALUE self){
@@ -501,10 +501,10 @@ static VALUE daemon_state(VALUE self){
501
501
  /*
502
502
  * Returns whether or not the service is in a running state, i.e. the service
503
503
  * status is either RUNNING, PAUSED or IDLE.
504
- *
504
+ *
505
505
  * This is typically used within your service_main method to setup the main
506
506
  * loop. For example:
507
- *
507
+ *
508
508
  * class MyDaemon < Daemon
509
509
  * def service_main
510
510
  * while running?
@@ -522,11 +522,11 @@ static VALUE daemon_is_running(VALUE self){
522
522
  ){
523
523
  v_bool = Qtrue;
524
524
  }
525
-
526
- return v_bool;
525
+
526
+ return v_bool;
527
527
  }
528
528
 
529
- /*
529
+ /*
530
530
  * This is a shortcut for Daemon.new + Daemon#mainloop.
531
531
  */
532
532
  static VALUE daemon_c_mainloop(VALUE klass){
@@ -552,17 +552,17 @@ void Init_daemon()
552
552
  rb_define_method(cDaemon, "mainloop", daemon_mainloop, 0);
553
553
  rb_define_method(cDaemon, "state", daemon_state, 0);
554
554
  rb_define_method(cDaemon, "running?", daemon_is_running, 0);
555
-
555
+
556
556
  rb_define_singleton_method(cDaemon, "mainloop", daemon_c_mainloop, 0);
557
557
 
558
558
  // Intialize critical section used by green polling thread
559
559
  InitializeCriticalSection(&csControlCode);
560
560
 
561
561
  // Constants
562
-
563
- /* 0.6.1: The version of this library */
562
+
563
+ /* 0.7.0: The version of this library */
564
564
  rb_define_const(cDaemon, "VERSION", rb_str_new2(WIN32_SERVICE_VERSION));
565
-
565
+
566
566
  /* Service has received a signal to resume but is not yet running */
567
567
  rb_define_const(cDaemon, "CONTINUE_PENDING",
568
568
  INT2NUM(SERVICE_CONTINUE_PENDING));
@@ -590,7 +590,7 @@ void Init_daemon()
590
590
  /* Service is stopped. */
591
591
  rb_define_const(cDaemon, "STOPPED",
592
592
  INT2NUM(SERVICE_STOPPED));
593
-
593
+
594
594
  /* Service is in an idle state */
595
595
  rb_define_const(cDaemon, "IDLE", INT2NUM(0));
596
596
  }