win32-service 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
data/lib/win32/service.rb CHANGED
@@ -23,7 +23,8 @@ module Win32
23
23
  include Windows::Process
24
24
  include Windows::Security
25
25
  include Windows::MSVCRT::String
26
- include Windows::MSVCRT::Buffer
26
+ include Windows::MSVCRT::Buffer
27
+
27
28
  extend Windows::Error
28
29
  extend Windows::Service
29
30
  extend Windows::File
@@ -32,7 +33,8 @@ module Win32
32
33
  extend Windows::MSVCRT::String
33
34
  extend Windows::MSVCRT::Buffer
34
35
 
35
- VERSION = '0.6.1'
36
+ # The version of the win32-service library
37
+ VERSION = '0.7.0'
36
38
 
37
39
  # SCM security and access rights
38
40
 
@@ -227,10 +229,14 @@ module Win32
227
229
 
228
230
  # :startdoc: #
229
231
 
230
- # Creates a new service with +service_name+ on +host+, or the local host
231
- # if no host is specified. The +options+ parameter is a hash that can
232
- # contain any of the following parameters, and their default values:
232
+ # Creates a new service with the specified +options+. A +service_name+
233
+ # must be specified or an ArgumentError is raised. A +host+ option may
234
+ # be specified. If no host is specified the local machine is used.
233
235
  #
236
+ # Possible Options:
237
+ #
238
+ # * service_name => nil (you must specify)
239
+ # * host => nil (optional)
234
240
  # * display_name => service_name
235
241
  # * desired_access => Service::ALL_ACCESS
236
242
  # * service_type => Service::WIN32_OWN_PROCESS |
@@ -252,7 +258,9 @@ module Win32
252
258
  # Example:
253
259
  #
254
260
  # # Configure everything
255
- # Service.new('some_service', nil,
261
+ # Service.new(
262
+ # :service_name => 'some_service',
263
+ # :host => 'localhost',
256
264
  # :service_type => Service::WIN32_OWN_PROCESS,
257
265
  # :description => 'A custom service I wrote just for fun',
258
266
  # :start_type => Service::AUTO_START,
@@ -265,10 +273,7 @@ module Win32
265
273
  # :display_name => 'This is some service',
266
274
  # )
267
275
  #
268
- def initialize(service_name, host=nil, options={})
269
- raise TypeError unless service_name.is_a?(String)
270
- raise TypeError if host && !host.is_a?(String)
271
-
276
+ def initialize(options={})
272
277
  unless options.is_a?(Hash)
273
278
  raise ArgumentError, 'options parameter must be a hash'
274
279
  end
@@ -294,7 +299,9 @@ module Win32
294
299
  'failure_reboot_message' => nil,
295
300
  'failure_command' => nil,
296
301
  'failure_actions' => nil,
297
- 'failure_delay' => 0
302
+ 'failure_delay' => 0,
303
+ 'host' => nil,
304
+ 'service_name' => nil
298
305
  }
299
306
 
300
307
  # Validate the hash options
@@ -305,6 +312,16 @@ module Win32
305
312
  end
306
313
  opts[key] = value
307
314
  }
315
+
316
+ unless opts['service_name']
317
+ raise ArgumentError, 'No service_name specified'
318
+ end
319
+
320
+ service_name = opts.delete('service_name')
321
+ host = opts.delete('host')
322
+
323
+ raise TypeError unless service_name.is_a?(String)
324
+ raise TypeError if host && !host.is_a?(String)
308
325
 
309
326
  handle_scm = OpenSCManager(host, 0, SC_MANAGER_CREATE_SERVICE)
310
327
 
@@ -408,10 +425,11 @@ module Win32
408
425
  # Examples:
409
426
  #
410
427
  # # Configure only the display name
411
- # Service.configure('some_service', nil, :display_name => 'Test 33')
428
+ # Service.configure(:service_name => 'some_service', :display_name => 'Test 33')
412
429
  #
413
430
  # # Configure everything
414
- # Service.configure('some_service', nil,
431
+ # Service.configure(
432
+ # :service_name => 'some_service'
415
433
  # :service_type => Service::WIN32_OWN_PROCESS,
416
434
  # :start_type => Service::AUTO_START,
417
435
  # :error_control => Service::ERROR_NORMAL,
@@ -424,9 +442,7 @@ module Win32
424
442
  # :description => 'A custom service I wrote just for fun'
425
443
  # )
426
444
  #
427
- def self.configure(service, host=nil, options={})
428
- raise TypeError unless service.is_a?(String)
429
-
445
+ def self.configure(options={})
430
446
  unless options.is_a?(Hash)
431
447
  raise ArgumentError, 'options parameter must be a hash'
432
448
  end
@@ -450,7 +466,9 @@ module Win32
450
466
  'failure_reboot_message' => nil,
451
467
  'failure_command' => nil,
452
468
  'failure_actions' => nil,
453
- 'failure_delay' => 0
469
+ 'failure_delay' => 0,
470
+ 'service_name' => nil,
471
+ 'host' => nil
454
472
  }
455
473
 
456
474
  # Validate the hash options
@@ -461,6 +479,16 @@ module Win32
461
479
  end
462
480
  opts[key] = value
463
481
  }
482
+
483
+ unless opts['service_name']
484
+ raise ArgumentError, 'No service_name specified'
485
+ end
486
+
487
+ service = opts.delete('service_name')
488
+ host = opts.delete('host')
489
+
490
+ raise TypeError unless service.is_a?(String)
491
+ raise TypeError unless host.is_a?(String) if host
464
492
 
465
493
  handle_scm = OpenSCManager(host, 0, SC_MANAGER_CONNECT)
466
494
 
@@ -861,9 +889,9 @@ module Win32
861
889
  CloseServiceHandle(handle_scs)
862
890
  CloseServiceHandle(handle_scm)
863
891
 
864
- binary_path_name = 0.chr * 260
865
- load_order_group = 0.chr * 260
866
- dependencies = 0.chr * 260
892
+ binary_path_name = 0.chr * 1024
893
+ load_order_group = 0.chr * 1024
894
+ dependencies = 0.chr * 1024
867
895
  service_start_name = 0.chr * 260
868
896
  display_name = 0.chr * 260
869
897
 
@@ -1095,15 +1123,15 @@ module Win32
1095
1123
  config_buf = get_config_info(handle_scs)
1096
1124
 
1097
1125
  if config_buf != ERROR_FILE_NOT_FOUND
1098
- binary_path = 0.chr * 260
1126
+ binary_path = 0.chr * 1024
1099
1127
  strcpy(binary_path, config_buf[12,4].unpack('L').first)
1100
1128
  binary_path = binary_path.unpack('Z*')[0]
1101
1129
 
1102
- load_order = 0.chr * 260
1130
+ load_order = 0.chr * 1024
1103
1131
  strcpy(load_order, config_buf[16,4].unpack('L').first)
1104
1132
  load_order = load_order.unpack('Z*')[0]
1105
1133
 
1106
- start_name = 0.chr * 260
1134
+ start_name = 0.chr * 1024
1107
1135
  strcpy(start_name, config_buf[28,4].unpack('L').first)
1108
1136
  start_name = start_name.unpack('Z*')[0]
1109
1137
 
@@ -1114,7 +1142,7 @@ module Win32
1114
1142
 
1115
1143
  deps = get_dependencies(config_buf[24,4].unpack('L').first)
1116
1144
 
1117
- description = 0.chr * 1024
1145
+ description = 0.chr * 2048
1118
1146
  buf = get_config2_info(handle_scs, SERVICE_CONFIG_DESCRIPTION)
1119
1147
 
1120
1148
  strcpy(description, buf[0,4].unpack('L').first)
@@ -7,6 +7,9 @@
7
7
  # These tests are rather limited, since the acid test is to install
8
8
  # your daemon as a service and see how it behaves.
9
9
  #########################################################################
10
+ require 'rubygems'
11
+ gem 'test-unit'
12
+
10
13
  require 'win32/daemon'
11
14
  require 'test/unit'
12
15
  include Win32
@@ -17,7 +20,7 @@ class TC_Daemon < Test::Unit::TestCase
17
20
  end
18
21
 
19
22
  def test_version
20
- assert_equal('0.6.1', Daemon::VERSION)
23
+ assert_equal('0.7.0', Daemon::VERSION)
21
24
  end
22
25
 
23
26
  def test_constructor
@@ -3,6 +3,9 @@
3
3
  #
4
4
  # Test case for the Win32::Service class.
5
5
  ##########################################################################
6
+ require 'rubygems'
7
+ gem 'test-unit'
8
+
6
9
  require 'win32/service'
7
10
  require 'socket'
8
11
  require 'test/unit'
@@ -20,19 +23,7 @@ class TC_Win32_Service < Test::Unit::TestCase
20
23
  end
21
24
 
22
25
  def test_version
23
- assert_equal('0.6.1', Win32::Service::VERSION)
24
- end
25
-
26
- def test_service_configure
27
- assert_respond_to(Win32::Service, :configure)
28
- end
29
-
30
- def test_service_configure_expected_errors
31
- assert_raise(ArgumentError){ Win32::Service.configure }
32
- assert_raise(ArgumentError){ Win32::Service.configure('bogus') }
33
- assert_raise(ArgumentError){ Win32::Service.configure('bogus', 'bogus') }
34
- assert_raise(Win32::Service::Error){ Win32::Service.configure('x', nil, :description => 'Test') }
35
- assert_raise(Win32::Service::Error){ Win32::Service.configure('x', 'y', :description => 'Test') }
26
+ assert_equal('0.7.0', Win32::Service::VERSION)
36
27
  end
37
28
 
38
29
  def test_services_basic
@@ -41,7 +32,7 @@ class TC_Win32_Service < Test::Unit::TestCase
41
32
  assert_nothing_raised{ Win32::Service.services(nil) }
42
33
  assert_nothing_raised{ Win32::Service.services(nil, 'network') }
43
34
  end
44
-
35
+
45
36
  def test_services_non_block_form
46
37
  assert_nothing_raised{ @services = Win32::Service.services }
47
38
  assert_kind_of(Array, @services)
@@ -0,0 +1,86 @@
1
+ #######################################################################
2
+ # test_win32_service_configure.rb
3
+ #
4
+ # Test suite that validates the Service.configure method.
5
+ #######################################################################
6
+ require 'rubygems'
7
+ gem 'test-unit'
8
+
9
+ require 'win32/service'
10
+ require 'test/unit'
11
+
12
+ class TC_Service_Configure < Test::Unit::TestCase
13
+ def self.startup
14
+ @@service = "notepad_service"
15
+ @@command = "C:\\windows\\system32\\notepad.exe"
16
+
17
+ Win32::Service.new(
18
+ :service_name => @@service,
19
+ :binary_path_name => @@command
20
+ )
21
+ end
22
+
23
+ def config_info
24
+ Win32::Service.config_info(@@service)
25
+ end
26
+
27
+ def full_info
28
+ service = nil
29
+ Win32::Service.services{ |s|
30
+ if s.service_name == @@service
31
+ service = s
32
+ break
33
+ end
34
+ }
35
+ service
36
+ end
37
+
38
+ def service_configure(opt)
39
+ options = {:service_name => @@service}
40
+ options = options.merge(opt)
41
+ assert_nothing_raised{ Win32::Service.configure(options) }
42
+ end
43
+
44
+ def setup
45
+ @info = Win32::Service.config_info(@@service)
46
+ end
47
+
48
+ def test_service_configure_basic
49
+ assert_respond_to(Win32::Service, :configure)
50
+ end
51
+
52
+ def test_service_type
53
+ assert_equal('own process, interactive', config_info.service_type)
54
+ service_configure(:service_type => Win32::Service::WIN32_SHARE_PROCESS)
55
+ assert_equal('share process', config_info.service_type)
56
+ end
57
+
58
+ def test_description
59
+ assert_equal('', full_info.description)
60
+ service_configure(:description => 'test service')
61
+ assert_equal('test service', full_info.description)
62
+ end
63
+
64
+ def test_start_type
65
+ assert_equal('demand start', config_info.start_type)
66
+ service_configure(:start_type => Win32::Service::DISABLED)
67
+ assert_equal('disabled', config_info.start_type)
68
+ end
69
+
70
+ def test_service_configure_expected_errors
71
+ assert_raise(ArgumentError){ Win32::Service.configure }
72
+ assert_raise(ArgumentError){ Win32::Service.configure('bogus') }
73
+ assert_raise(ArgumentError){ Win32::Service.configure({}) }
74
+ assert_raise(ArgumentError){ Win32::Service.configure(:binary_path_name => 'notepad.exe') }
75
+ end
76
+
77
+ def teardown
78
+ @info = nil
79
+ end
80
+
81
+ def self.shutdown
82
+ Win32::Service.delete(@@service) if Win32::Service.exists?(@@service)
83
+ @@service = nil
84
+ @@command = nil
85
+ end
86
+ end
@@ -0,0 +1,103 @@
1
+ ########################################################################
2
+ # tc_service_create.rb
3
+ #
4
+ # Test case for the Service.create method. This test case will create
5
+ # a dummy (notepad) service. It won't actually run of course.
6
+ ########################################################################
7
+ require 'rubygems'
8
+ gem 'test-unit'
9
+
10
+ require 'win32/service'
11
+ require 'test/unit'
12
+
13
+ class TC_Service_Create < Test::Unit::TestCase
14
+ def self.startup
15
+ @@service1 = "notepad_service1"
16
+ @@service2 = "notepad_service2"
17
+ @@command = "C:\\windows\\system32\\notepad.exe"
18
+
19
+ Win32::Service.new(
20
+ :service_name => @@service1,
21
+ :binary_path_name => @@command
22
+ )
23
+
24
+ Win32::Service.new(
25
+ :service_name => @@service2,
26
+ :display_name => 'Notepad Test',
27
+ :desired_access => Win32::Service::ALL_ACCESS,
28
+ :service_type => Win32::Service::WIN32_OWN_PROCESS,
29
+ :start_type => Win32::Service::DISABLED,
30
+ :error_control => Win32::Service::ERROR_IGNORE,
31
+ :binary_path_name => @@command,
32
+ :load_order_group => 'Network',
33
+ :dependencies => 'W32Time',
34
+ :description => 'Test service. Please delete me'
35
+ )
36
+ end
37
+
38
+ def setup
39
+ @info1 = Win32::Service.config_info(@@service1)
40
+ @info2 = Win32::Service.config_info(@@service2)
41
+ end
42
+
43
+ def test_new_basic
44
+ assert_respond_to(Win32::Service, :new)
45
+ end
46
+
47
+ def test_create_alias
48
+ assert_respond_to(Win32::Service, :create)
49
+ assert_equal(Win32::Service.method(:create), Win32::Service.method(:new))
50
+ end
51
+
52
+ # Sanity test to ensure the services were actually created. If this test
53
+ # fails, the results for other tests are meaningless.
54
+ #
55
+ def test_service_created
56
+ assert_true(Win32::Service.exists?(@@service1))
57
+ assert_true(Win32::Service.exists?(@@service2))
58
+ end
59
+
60
+ def test_service_configuration_info
61
+ assert_equal('own process, interactive', @info1.service_type)
62
+ assert_equal('demand start', @info1.start_type)
63
+ assert_equal('normal', @info1.error_control)
64
+ assert_equal(@@command, @info1.binary_path_name)
65
+ assert_equal('', @info1.load_order_group)
66
+ assert_equal(0, @info1.tag_id)
67
+ assert_equal([], @info1.dependencies)
68
+ assert_equal('LocalSystem', @info1.service_start_name)
69
+ assert_equal('notepad_service1', @info1.display_name)
70
+ end
71
+
72
+ def test_service_configuration_info_multiple_options
73
+ assert_equal('own process', @info2.service_type)
74
+ assert_equal('disabled', @info2.start_type)
75
+ assert_equal('ignore', @info2.error_control)
76
+ assert_equal(@@command, @info2.binary_path_name)
77
+ assert_equal('Network', @info2.load_order_group)
78
+ assert_equal(0, @info2.tag_id)
79
+ assert_equal(['W32Time'], @info2.dependencies)
80
+ assert_equal('LocalSystem', @info2.service_start_name)
81
+ assert_equal('Notepad Test', @info2.display_name)
82
+ end
83
+
84
+ def test_create_expected_errors
85
+ assert_raise(ArgumentError){ Win32::Service.new }
86
+ assert_raise(ArgumentError){ Win32::Service.new(:binary_path_name => 'test.exe') }
87
+ assert_raise(ArgumentError){ Win32::Service.new(:bogus => 'test.exe') }
88
+ end
89
+
90
+ def teardown
91
+ @info1 = nil
92
+ @info2 = nil
93
+ end
94
+
95
+ def self.shutdown
96
+ Win32::Service.delete(@@service1) if Win32::Service.exists?(@@service1)
97
+ Win32::Service.delete(@@service2) if Win32::Service.exists?(@@service2)
98
+
99
+ @@service1 = nil
100
+ @@service2 = nil
101
+ @@command = nil
102
+ end
103
+ end
@@ -3,13 +3,19 @@
3
3
  #
4
4
  # Test case for the Struct::ServiceInfo structure.
5
5
  ########################################################################
6
+ require 'rubygems'
7
+ gem 'test-unit'
8
+
6
9
  require 'win32/service'
7
10
  require 'test/unit'
8
11
 
9
12
  class TC_Struct_ServiceInfo < Test::Unit::TestCase
13
+ def self.startup
14
+ @@services = Win32::Service.services
15
+ end
16
+
10
17
  def setup
11
- @services = Win32::Service.services
12
- @service_info = @services[0]
18
+ @service_info = @@services[0]
13
19
 
14
20
  @error_controls = [
15
21
  'critical',
@@ -162,9 +168,12 @@ class TC_Struct_ServiceInfo < Test::Unit::TestCase
162
168
  end
163
169
 
164
170
  def teardown
165
- @services = nil
166
171
  @types = nil
167
172
  @states = nil
168
173
  @controls = nil
169
174
  end
175
+
176
+ def self.shutdown
177
+ @@services = nil
178
+ end
170
179
  end