win32-service 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.6.1 - 1-Jan-2008
2
+ * The Service.services method now handles the scenario where a particular
3
+ service may still exist, but its underlying registry entry has been deleted.
4
+ In this case, most ServiceInfo struct members are set to nil and a warning
5
+ is issued.
6
+ * RDoc updates.
7
+
1
8
  == 0.6.0 - 25-Nov-2007
2
9
  * The Service control class is now pure Ruby. The Daemon class is still C,
3
10
  however. That may change in the future. This means the windows-pr
data/doc/daemon.txt CHANGED
@@ -140,7 +140,7 @@ Daemon::IDLE
140
140
  service responsiveness issues.
141
141
 
142
142
  = Copyright
143
- (C) 2003-2007 Daniel J. Berger, All Rights Reserved
143
+ (C) 2003-2008 Daniel J. Berger, All Rights Reserved
144
144
 
145
145
  = License
146
146
  Ruby's
data/doc/service.txt CHANGED
@@ -16,8 +16,6 @@
16
16
  require "win32/service"
17
17
  include Win32
18
18
 
19
- s = Service.new("some_machine")
20
-
21
19
  # Create a new service
22
20
  Service.create('some_service', nil,
23
21
  :service_type => Service::WIN32_OWN_PROCESS,
@@ -352,7 +350,7 @@ Service::ERROR_CRITICAL
352
350
  Use RegisterServiceCtrlHandlerEx().
353
351
 
354
352
  = Copyright
355
- (C) 2003-2007, Daniel J. Berger, All Rights Reserved
353
+ (C) 2003-2008, Daniel J. Berger, All Rights Reserved
356
354
 
357
355
  = License
358
356
  Ruby's
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.0"
8
+ #define WIN32_SERVICE_VERSION "0.6.1"
9
9
 
10
10
  static VALUE cDaemonError;
11
11
 
@@ -482,15 +482,15 @@ static VALUE daemon_mainloop(VALUE self)
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
- * loop. For example:
485
+ * loop. For example:
486
486
  *
487
- * class MyDaemon < Daemon
488
- * def service_main
489
- * while state == RUNNING || state == PAUSED || state == IDLE
490
- * # Your main loop here
491
- * end
492
- * end
493
- * end
487
+ * class MyDaemon < Daemon
488
+ * def service_main
489
+ * while state == RUNNING || state == PAUSED || state == IDLE
490
+ * # Your main loop here
491
+ * end
492
+ * end
493
+ * end
494
494
  *
495
495
  * See the Daemon#running? method for an abstraction of the above code.
496
496
  */
@@ -503,15 +503,15 @@ static VALUE daemon_state(VALUE self){
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
- * loop. For example:
506
+ * loop. For example:
507
507
  *
508
- * class MyDaemon < Daemon
509
- * def service_main
510
- * while running?
511
- * # Your main loop here
508
+ * class MyDaemon < Daemon
509
+ * def service_main
510
+ * while running?
511
+ * # Your main loop here
512
+ * end
512
513
  * end
513
514
  * end
514
- * end
515
515
  */
516
516
  static VALUE daemon_is_running(VALUE self){
517
517
  VALUE v_bool = Qfalse;
@@ -527,7 +527,7 @@ static VALUE daemon_is_running(VALUE self){
527
527
  }
528
528
 
529
529
  /*
530
- * This is a shortcut for Daemon#new + Daemon#mainloop.
530
+ * This is a shortcut for Daemon.new + Daemon#mainloop.
531
531
  */
532
532
  static VALUE daemon_c_mainloop(VALUE klass){
533
533
  VALUE v_args[1];
@@ -537,11 +537,15 @@ static VALUE daemon_c_mainloop(VALUE klass){
537
537
 
538
538
  void Init_daemon()
539
539
  {
540
- VALUE mWin32, cDaemon;
540
+ /* The Win32 module serves as a namespace only. */
541
+ VALUE mWin32 = rb_define_module("Win32");
542
+
543
+ /* The Daemon class encapsulates a Windows service through the use
544
+ * of callback methods and a main loop.
545
+ */
546
+ VALUE cDaemon = rb_define_class_under(mWin32, "Daemon", rb_cObject);
541
547
 
542
- // Modules and classes
543
- mWin32 = rb_define_module("Win32");
544
- cDaemon = rb_define_class_under(mWin32, "Daemon", rb_cObject);
548
+ /* Error typically raised if something goes wrong with your daemon. */
545
549
  cDaemonError = rb_define_class_under(cDaemon, "Error", rb_eStandardError);
546
550
 
547
551
  rb_define_alloc_func(cDaemon, daemon_allocate);
@@ -556,7 +560,7 @@ void Init_daemon()
556
560
 
557
561
  // Constants
558
562
 
559
- /* 0.6.0: The version of this library */
563
+ /* 0.6.1: The version of this library */
560
564
  rb_define_const(cDaemon, "VERSION", rb_str_new2(WIN32_SERVICE_VERSION));
561
565
 
562
566
  /* Service has received a signal to resume but is not yet running */
data/lib/win32/service.rb CHANGED
@@ -6,8 +6,15 @@ require 'windows/security'
6
6
  require 'windows/msvcrt/string'
7
7
  require 'windows/msvcrt/buffer'
8
8
 
9
+ # The Win32 module serves as a namespace only.
9
10
  module Win32
11
+
12
+ # The Service class encapsulates services controller actions, such as
13
+ # creating, starting, configuring or deleting services.
10
14
  class Service
15
+
16
+ # This is the error typically raised if one of the Service methods
17
+ # should fail for any reason.
11
18
  class Error < StandardError; end
12
19
 
13
20
  include Windows::Error
@@ -25,7 +32,7 @@ module Win32
25
32
  extend Windows::MSVCRT::String
26
33
  extend Windows::MSVCRT::Buffer
27
34
 
28
- VERSION = '0.6.0'
35
+ VERSION = '0.6.1'
29
36
 
30
37
  # SCM security and access rights
31
38
 
@@ -197,6 +204,7 @@ module Win32
197
204
  # Run a command
198
205
  ACTION_RUN_COMMAND = SC_ACTION_RUN_COMMAND
199
206
 
207
+ # :stopdoc: #
200
208
  StatusStruct = Struct.new('ServiceStatus', :service_type,
201
209
  :current_state, :controls_accepted, :win32_exit_code,
202
210
  :service_specific_exit_code, :check_point, :wait_hint, :interactive,
@@ -216,6 +224,8 @@ module Win32
216
224
  :description, :interactive, :pid, :service_flags, :reset_period,
217
225
  :reboot_message, :command, :num_actions, :actions
218
226
  )
227
+
228
+ # :startdoc: #
219
229
 
220
230
  # Creates a new service with +service_name+ on +host+, or the local host
221
231
  # if no host is specified. The +options+ parameter is a hash that can
@@ -242,7 +252,7 @@ module Win32
242
252
  # Example:
243
253
  #
244
254
  # # Configure everything
245
- # Service.create('some_service', nil,
255
+ # Service.new('some_service', nil,
246
256
  # :service_type => Service::WIN32_OWN_PROCESS,
247
257
  # :description => 'A custom service I wrote just for fun',
248
258
  # :start_type => Service::AUTO_START,
@@ -1084,59 +1094,81 @@ module Win32
1084
1094
 
1085
1095
  config_buf = get_config_info(handle_scs)
1086
1096
 
1087
- binary_path = 0.chr * 260
1088
- strcpy(binary_path, config_buf[12,4].unpack('L').first)
1089
- binary_path = binary_path.unpack('Z*')[0]
1097
+ if config_buf != ERROR_FILE_NOT_FOUND
1098
+ binary_path = 0.chr * 260
1099
+ strcpy(binary_path, config_buf[12,4].unpack('L').first)
1100
+ binary_path = binary_path.unpack('Z*')[0]
1090
1101
 
1091
- load_order = 0.chr * 260
1092
- strcpy(load_order, config_buf[16,4].unpack('L').first)
1093
- load_order = load_order.unpack('Z*')[0]
1102
+ load_order = 0.chr * 260
1103
+ strcpy(load_order, config_buf[16,4].unpack('L').first)
1104
+ load_order = load_order.unpack('Z*')[0]
1094
1105
 
1095
- start_name = 0.chr * 260
1096
- strcpy(start_name, config_buf[28,4].unpack('L').first)
1097
- start_name = start_name.unpack('Z*')[0]
1106
+ start_name = 0.chr * 260
1107
+ strcpy(start_name, config_buf[28,4].unpack('L').first)
1108
+ start_name = start_name.unpack('Z*')[0]
1098
1109
 
1099
- start_type = get_start_type(config_buf[4,4].unpack('L').first)
1100
- error_control = get_error_control(config_buf[8,4].unpack('L').first)
1110
+ start_type = get_start_type(config_buf[4,4].unpack('L').first)
1111
+ error_ctrl = get_error_control(config_buf[8,4].unpack('L').first)
1101
1112
 
1102
- tag_id = config_buf[20,4].unpack('L').first
1113
+ tag_id = config_buf[20,4].unpack('L').first
1103
1114
 
1104
- dependencies = get_dependencies(config_buf[24,4].unpack('L').first)
1115
+ deps = get_dependencies(config_buf[24,4].unpack('L').first)
1105
1116
 
1106
- description = 0.chr * 1024
1107
- buf = get_config2_info(handle_scs, SERVICE_CONFIG_DESCRIPTION)
1117
+ description = 0.chr * 1024
1118
+ buf = get_config2_info(handle_scs, SERVICE_CONFIG_DESCRIPTION)
1108
1119
 
1109
- strcpy(description, buf[0,4].unpack('L').first)
1110
- description = description.unpack('Z*')[0]
1120
+ strcpy(description, buf[0,4].unpack('L').first)
1121
+ description = description.unpack('Z*')[0]
1122
+ else
1123
+ msg = "WARNING: The registry entry for the #{service_name} "
1124
+ msg += "service could not be found."
1125
+ warn msg
1126
+
1127
+ binary_path = nil
1128
+ load_order = nil
1129
+ start_name = nil
1130
+ start_type = nil
1131
+ error_ctrl = nil
1132
+ tag_id = nil
1133
+ deps = nil
1134
+ description = nil
1135
+ end
1111
1136
 
1112
1137
  buf2 = get_config2_info(handle_scs, SERVICE_CONFIG_FAILURE_ACTIONS)
1113
1138
 
1114
- reset_period = buf2[0,4].unpack('L').first
1139
+ if buf2 != ERROR_FILE_NOT_FOUND
1140
+ reset_period = buf2[0,4].unpack('L').first
1115
1141
 
1116
- reboot_msg = 0.chr * 260
1117
- strcpy(reboot_msg, buf2[4,4].unpack('L').first)
1118
- reboot_msg = reboot_msg.unpack('Z*')[0]
1142
+ reboot_msg = 0.chr * 260
1143
+ strcpy(reboot_msg, buf2[4,4].unpack('L').first)
1144
+ reboot_msg = reboot_msg.unpack('Z*')[0]
1119
1145
 
1120
- command = 0.chr * 260
1121
- strcpy(command, buf2[8,4].unpack('L').first)
1122
- command = command.unpack('Z*')[0]
1146
+ command = 0.chr * 260
1147
+ strcpy(command, buf2[8,4].unpack('L').first)
1148
+ command = command.unpack('Z*')[0]
1123
1149
 
1124
- num_actions = buf2[12,4].unpack('L').first
1125
- actions = nil
1150
+ num_actions = buf2[12,4].unpack('L').first
1151
+ actions = nil
1126
1152
 
1127
- if num_actions > 0
1128
- action_ptr = buf2[16,4].unpack('L').first
1129
- action_buf = [0,0].pack('LL') * num_actions
1130
- memcpy(action_buf, action_ptr, action_buf.size)
1153
+ if num_actions > 0
1154
+ action_ptr = buf2[16,4].unpack('L').first
1155
+ action_buf = [0,0].pack('LL') * num_actions
1156
+ memcpy(action_buf, action_ptr, action_buf.size)
1131
1157
 
1132
- i = 0
1133
- actions = {}
1134
- num_actions.times{ |n|
1135
- action_type, delay = action_buf[i, 8].unpack('LL')
1136
- action_type = get_action_type(action_type)
1137
- actions[n+1] = {:action_type => action_type, :delay => delay}
1138
- i += 8
1139
- }
1158
+ i = 0
1159
+ actions = {}
1160
+ num_actions.times{ |n|
1161
+ action_type, delay = action_buf[i, 8].unpack('LL')
1162
+ action_type = get_action_type(action_type)
1163
+ actions[n+1] = {:action_type => action_type, :delay => delay}
1164
+ i += 8
1165
+ }
1166
+ end
1167
+ else
1168
+ reset_period = nil
1169
+ reboot_message = nil
1170
+ command = nil
1171
+ actions = nil
1140
1172
  end
1141
1173
 
1142
1174
  CloseServiceHandle(handle_scs)
@@ -1153,11 +1185,11 @@ module Win32
1153
1185
  wait_hint,
1154
1186
  binary_path,
1155
1187
  start_type,
1156
- error_control,
1188
+ error_ctrl,
1157
1189
  load_order,
1158
1190
  tag_id,
1159
1191
  start_name,
1160
- dependencies,
1192
+ deps,
1161
1193
  description,
1162
1194
  interactive,
1163
1195
  pid,
@@ -1316,7 +1348,10 @@ module Win32
1316
1348
  end
1317
1349
  end
1318
1350
 
1319
- # Shortcut for QueryServiceConfig. Returns the buffer.
1351
+ # Shortcut for QueryServiceConfig. Returns the buffer. In rare cases
1352
+ # the underlying registry entry may have been deleted, but the service
1353
+ # still exists. In that case, the ERROR_FILE_NOT_FOUND value is returned
1354
+ # instead.
1320
1355
  #
1321
1356
  def self.get_config_info(handle)
1322
1357
  bytes_needed = [0].pack('L')
@@ -1328,6 +1363,8 @@ module Win32
1328
1363
 
1329
1364
  if !bool && err_num == ERROR_INSUFFICIENT_BUFFER
1330
1365
  config_buf = 0.chr * bytes_needed.unpack('L').first
1366
+ elsif err_num == ERROR_FILE_NOT_FOUND
1367
+ return err_num
1331
1368
  else
1332
1369
  error = get_last_error(err_num)
1333
1370
  CloseServiceHandle(handle)
@@ -1361,13 +1398,15 @@ module Win32
1361
1398
  # First attempt at QueryServiceConfig2 is to get size needed
1362
1399
  bool = QueryServiceConfig2(handle, info_level, 0, 0, bytes_needed)
1363
1400
 
1364
- error = GetLastError()
1401
+ err_num = GetLastError()
1365
1402
 
1366
- if !bool && error == ERROR_INSUFFICIENT_BUFFER
1403
+ if !bool && err_num == ERROR_INSUFFICIENT_BUFFER
1367
1404
  config2_buf = 0.chr * bytes_needed.unpack('L').first
1405
+ elsif err_num == ERROR_FILE_NOT_FOUND
1406
+ return err_num
1368
1407
  else
1369
1408
  CloseServiceHandle(handle)
1370
- raise Error, error
1409
+ raise Error, get_last_error(err_num)
1371
1410
  end
1372
1411
 
1373
1412
  bytes_needed = [0].pack('L')
@@ -1382,8 +1421,9 @@ module Win32
1382
1421
  )
1383
1422
 
1384
1423
  unless bool
1424
+ error = GetLastError()
1385
1425
  CloseServiceHandle(handle)
1386
- raise Error, get_last_error
1426
+ raise Error, get_last_error(error)
1387
1427
  end
1388
1428
 
1389
1429
  config2_buf
data/test/tc_daemon.rb CHANGED
@@ -17,7 +17,7 @@ class TC_Daemon < Test::Unit::TestCase
17
17
  end
18
18
 
19
19
  def test_version
20
- assert_equal('0.6.0', Daemon::VERSION)
20
+ assert_equal('0.6.1', Daemon::VERSION)
21
21
  end
22
22
 
23
23
  def test_constructor
data/test/tc_service.rb CHANGED
@@ -20,7 +20,7 @@ class TC_Win32_Service < Test::Unit::TestCase
20
20
  end
21
21
 
22
22
  def test_version
23
- assert_equal('0.6.0', Win32::Service::VERSION)
23
+ assert_equal('0.6.1', Win32::Service::VERSION)
24
24
  end
25
25
 
26
26
  def test_service_configure
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: win32-service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Berger
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2007-11-25 00:00:00 -07:00
12
+ date: 2008-01-01 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -35,18 +35,18 @@ extra_rdoc_files:
35
35
  - doc/service.txt
36
36
  - doc/daemon.txt
37
37
  files:
38
+ - doc/daemon.txt
39
+ - doc/service.txt
38
40
  - test/tc_daemon.rb
39
41
  - test/tc_service.rb
40
42
  - test/tc_service_create.rb
41
43
  - test/tc_service_info.rb
42
44
  - test/tc_service_status.rb
43
45
  - lib/win32/service.rb
46
+ - ext/win32/daemon.c
44
47
  - CHANGES
45
48
  - README
46
49
  - MANIFEST
47
- - ext/win32/daemon.c
48
- - doc/service.txt
49
- - doc/daemon.txt
50
50
  has_rdoc: true
51
51
  homepage: http://www.rubyforge.org/projects/win32utils
52
52
  post_install_message:
@@ -69,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
69
  requirements: []
70
70
 
71
71
  rubyforge_project: win32utils
72
- rubygems_version: 0.9.5
72
+ rubygems_version: 1.0.1
73
73
  signing_key:
74
74
  specification_version: 2
75
75
  summary: An library for controlling and creating MS Windows services