win32-service 0.6.1-x86-mswin32-60 → 0.7.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
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,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
@@ -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