win32-taskscheduler 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MREwDwYDVQQDDAhkamJl
3
+ cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
4
+ MB4XDTE2MTIxMjAwMTQ1M1oXDTE3MTIxMjAwMTQ1M1owPzERMA8GA1UEAwwIZGpi
5
+ ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
6
+ bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVtTm/wETO8yKVKRPBO
7
+ VgPRvE94iEfKryOb/tQrmhGhchG2ALqdw/r54cGJvLaXeItrYJ6N8pSE/FSnN5jM
8
+ xugUhHBprPl+AsQ4E+IBy0dKwyU8XjFoVYzWvT1wnqwQdSazdgFCfQqb51QCgUIT
9
+ PGGakKlyzCb3Mbq30is8+QlRrqXt/JbpkUZbQwUqCdAulMT4oyPBk/L+48pbVX0s
10
+ 4yj7YaVAqfGByAMTPXEmUS388lX+0xq8+GGir2Fuh0TpNW0ggr9BxprwqL0Mg4Oo
11
+ YhM5L1y8Plolo8mOTN3+K8I3afZ0lD0BtwniVb6g+Ut/4aBjKy2+GyFwwNOu0gSj
12
+ desCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFJfg
13
+ HmQ0uDU3Z9A9hB1lQMjr5VZSMB0GA1UdEQQWMBSBEmRqYmVyZzk2QGdtYWlsLmNv
14
+ bTAdBgNVHRIEFjAUgRJkamJlcmc5NkBnbWFpbC5jb20wDQYJKoZIhvcNAQEFBQAD
15
+ ggEBACjRCHRP944MHIQJNCglZbDnZowybV2HxmG1uhnvRwrOjBA7CXemc+QSAL7K
16
+ 7eXC4FdojVEJrnU7ZxuCmfQU+fvkEQKOnah1osG1874aPiDlwtjHclpeqcDgTUI7
17
+ A7CF+OXK8x7ksFx205ruhPHKaPYtwVG/W/J+y7Wx8yl9rvwUgRBL5cVzTBiEz+AB
18
+ NRT7yoHXXfFXjuQWN1eHunSbNds2ZTGQd64yBCujb17Xdl+F9tu4klkTga3gxP3P
19
+ y3zoX1VttxnIZBojRM/s2A7c2aubMH2SVbXMR3ccVkB9XbYKl1OvCe7q85xEHit2
20
+ Kbpico5nnyHqf7YSPmvZe8bCU94=
21
+ -----END CERTIFICATE-----
@@ -1,56 +1,56 @@
1
- #######################################################################
2
- # taskscheduler_example.rb
3
- #
4
- # A test script for general futzing. You can run this example via the
5
- # 'example' rake task.
6
- #
7
- # Modify as you see fit.
8
- #######################################################################
9
- require 'win32/taskscheduler'
10
- require 'fileutils'
11
- require 'pp'
12
- include Win32
13
-
14
- puts 'VERSION: ' + TaskScheduler::VERSION
15
-
16
- ts = TaskScheduler.new
17
-
18
- trigger = {
19
- "start_year" => 2009,
20
- "start_month" => 4,
21
- "start_day" => 11,
22
- "start_hour" => 7,
23
- "start_minute" => 14,
24
- "trigger_type" => TaskScheduler::DAILY,
25
- "type" => { "days_interval" => 1 }
26
- }
27
-
28
- unless ts.enum.grep(/foo/).length > 0
29
- ts.new_work_item("foo", trigger)
30
- ts.application_name = "notepad.exe"
31
- ts.save
32
- puts "Task Added"
33
- end
34
-
35
- ts.activate("foo")
36
- ts.priority = TaskScheduler::IDLE
37
- ts.working_directory = "C:\\"
38
-
39
- puts "App name: " + ts.application_name
40
- puts "Creator: " + ts.creator
41
- puts "Exit code: " + ts.exit_code.to_s
42
- puts "Flags: " + ts.flags.to_s
43
- puts "Max run time: " + ts.max_run_time.to_s
44
- puts "Next run time: " + ts.next_run_time.to_s
45
- puts "Parameters: " + ts.parameters
46
- puts "Priority: " + ts.priority.to_s
47
- puts "Status: " + ts.status
48
- puts "Trigger count: " + ts.trigger_count.to_s
49
- puts "Trigger string: " + ts.trigger_string(0)
50
- puts "Working directory: " + ts.working_directory
51
- puts "Trigger: "
52
-
53
- pp ts.trigger(0)
54
-
55
- ts.delete("foo")
56
- puts "Task deleted"
1
+ #######################################################################
2
+ # taskscheduler_example.rb
3
+ #
4
+ # A test script for general futzing. You can run this example via the
5
+ # 'example' rake task.
6
+ #
7
+ # Modify as you see fit.
8
+ #######################################################################
9
+ require 'win32/taskscheduler'
10
+ require 'fileutils'
11
+ require 'pp'
12
+ include Win32
13
+
14
+ puts 'VERSION: ' + TaskScheduler::VERSION
15
+
16
+ ts = TaskScheduler.new
17
+
18
+ trigger = {
19
+ "start_year" => 2009,
20
+ "start_month" => 4,
21
+ "start_day" => 11,
22
+ "start_hour" => 7,
23
+ "start_minute" => 14,
24
+ "trigger_type" => TaskScheduler::DAILY,
25
+ "type" => { "days_interval" => 1 }
26
+ }
27
+
28
+ unless ts.enum.grep(/foo/).length > 0
29
+ ts.new_work_item("foo", trigger)
30
+ ts.application_name = "notepad.exe"
31
+ ts.save
32
+ puts "Task Added"
33
+ end
34
+
35
+ ts.activate("foo")
36
+ ts.priority = TaskScheduler::IDLE
37
+ ts.working_directory = "C:\\"
38
+
39
+ puts "App name: " + ts.application_name
40
+ puts "Creator: " + ts.creator
41
+ puts "Exit code: " + ts.exit_code.to_s
42
+ puts "Flags: " + ts.flags.to_s
43
+ puts "Max run time: " + ts.max_run_time.to_s
44
+ puts "Next run time: " + ts.next_run_time.to_s
45
+ puts "Parameters: " + ts.parameters
46
+ puts "Priority: " + ts.priority.to_s
47
+ puts "Status: " + ts.status
48
+ puts "Trigger count: " + ts.trigger_count.to_s
49
+ puts "Trigger string: " + ts.trigger_string(0)
50
+ puts "Working directory: " + ts.working_directory
51
+ puts "Trigger: "
52
+
53
+ pp ts.trigger(0)
54
+
55
+ ts.delete("foo")
56
+ puts "Task deleted"
@@ -0,0 +1 @@
1
+ require_relative 'win32/taskscheduler'
@@ -1,1368 +1,1383 @@
1
- require File.join(File.dirname(__FILE__), 'windows', 'helper')
2
- require 'win32ole'
3
- require 'socket'
4
- require 'time'
5
- require 'structured_warnings'
6
-
7
- # The Win32 module serves as a namespace only
8
- module Win32
9
-
10
- # The TaskScheduler class encapsulates a Windows scheduled task
11
- class TaskScheduler
12
- include Windows::Helper
13
-
14
- # The version of the win32-taskscheduler library
15
- VERSION = '0.3.1'
16
-
17
- # The Error class is typically raised if any TaskScheduler methods fail.
18
- class Error < StandardError; end
19
-
20
- # Triggers
21
-
22
- # Trigger is set to run the task a single tim
23
- TASK_TIME_TRIGGER_ONCE = 0
24
-
25
- # Trigger is set to run the task on a daily interval
26
- TASK_TIME_TRIGGER_DAILY = 1
27
-
28
- # Trigger is set to run the task on specific days of a specific week & month
29
- TASK_TIME_TRIGGER_WEEKLY = 2
30
-
31
- # Trigger is set to run the task on specific day(s) of the month
32
- TASK_TIME_TRIGGER_MONTHLYDATE = 3
33
-
34
- # Trigger is set to run the task on specific day(s) of the month
35
- TASK_TIME_TRIGGER_MONTHLYDOW = 4
36
-
37
- # Trigger is set to run the task if the system remains idle for the amount
38
- # of time specified by the idle wait time of the task
39
- TASK_EVENT_TRIGGER_ON_IDLE = 5
40
-
41
- # Trigger is set to run the task at system startup
42
- TASK_EVENT_TRIGGER_AT_SYSTEMSTART = 6
43
-
44
- # Trigger is set to run the task when a user logs on
45
- TASK_EVENT_TRIGGER_AT_LOGON = 7
46
-
47
- # Daily Tasks
48
-
49
- # The task will run on Sunday
50
- TASK_SUNDAY = 0x1
51
-
52
- # The task will run on Monday
53
- TASK_MONDAY = 0x2
54
-
55
- # The task will run on Tuesday
56
- TASK_TUESDAY = 0x4
57
-
58
- # The task will run on Wednesday
59
- TASK_WEDNESDAY = 0x8
60
-
61
- # The task will run on Thursday
62
- TASK_THURSDAY = 0x10
63
-
64
- # The task will run on Friday
65
- TASK_FRIDAY = 0x20
66
-
67
- # The task will run on Saturday
68
- TASK_SATURDAY = 0x40
69
-
70
- # Weekly tasks
71
-
72
- # The task will run between the 1st and 7th day of the month
73
- TASK_FIRST_WEEK = 1
74
-
75
- # The task will run between the 8th and 14th day of the month
76
- TASK_SECOND_WEEK = 2
77
-
78
- # The task will run between the 15th and 21st day of the month
79
- TASK_THIRD_WEEK = 3
80
-
81
- # The task will run between the 22nd and 28th day of the month
82
- TASK_FOURTH_WEEK = 4
83
-
84
- # The task will run the last seven days of the month
85
- TASK_LAST_WEEK = 5
86
-
87
- # Monthly tasks
88
-
89
- # The task will run in January
90
- TASK_JANUARY = 0x1
91
-
92
- # The task will run in February
93
- TASK_FEBRUARY = 0x2
94
-
95
- # The task will run in March
96
- TASK_MARCH = 0x4
97
-
98
- # The task will run in April
99
- TASK_APRIL = 0x8
100
-
101
- # The task will run in May
102
- TASK_MAY = 0x10
103
-
104
- # The task will run in June
105
- TASK_JUNE = 0x20
106
-
107
- # The task will run in July
108
- TASK_JULY = 0x40
109
-
110
- # The task will run in August
111
- TASK_AUGUST = 0x80
112
-
113
- # The task will run in September
114
- TASK_SEPTEMBER = 0x100
115
-
116
- # The task will run in October
117
- TASK_OCTOBER = 0x200
118
-
119
- # The task will run in November
120
- TASK_NOVEMBER = 0x400
121
-
122
- # The task will run in December
123
- TASK_DECEMBER = 0x800
124
-
125
- # Flags
126
-
127
- # Used when converting AT service jobs into work items
128
- TASK_FLAG_INTERACTIVE = 0x1
129
-
130
- # The work item will be deleted when there are no more scheduled run times
131
- TASK_FLAG_DELETE_WHEN_DONE = 0x2
132
-
133
- # The work item is disabled. Useful for temporarily disabling a task
134
- TASK_FLAG_DISABLED = 0x4
135
-
136
- # The work item begins only if the computer is not in use at the scheduled
137
- # start time
138
- TASK_FLAG_START_ONLY_IF_IDLE = 0x10
139
-
140
- # The work item terminates if the computer makes an idle to non-idle
141
- # transition while the work item is running
142
- TASK_FLAG_KILL_ON_IDLE_END = 0x20
143
-
144
- # The work item does not start if the computer is running on battery power
145
- TASK_FLAG_DONT_START_IF_ON_BATTERIES = 0x40
146
-
147
- # The work item ends, and the associated application quits, if the computer
148
- # switches to battery power
149
- TASK_FLAG_KILL_IF_GOING_ON_BATTERIES = 0x80
150
-
151
- # The work item starts only if the computer is in a docking station
152
- TASK_FLAG_RUN_ONLY_IF_DOCKED = 0x100
153
-
154
- # The work item created will be hidden
155
- TASK_FLAG_HIDDEN = 0x200
156
-
157
- # The work item runs only if there is a valid internet connection
158
- TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET = 0x400
159
-
160
- # The work item starts again if the computer makes a non-idle to idle
161
- # transition
162
- TASK_FLAG_RESTART_ON_IDLE_RESUME = 0x800
163
-
164
- # The work item causes the system to be resumed, or awakened, if the
165
- # system is running on batter power
166
- TASK_FLAG_SYSTEM_REQUIRED = 0x1000
167
-
168
- # The work item runs only if a specified account is logged on interactively
169
- TASK_FLAG_RUN_ONLY_IF_LOGGED_ON = 0x2000
170
-
171
- # Triggers
172
-
173
- # The task will stop at some point in time
174
- TASK_TRIGGER_FLAG_HAS_END_DATE = 0x1
175
-
176
- # The task can be stopped at the end of the repetition period
177
- TASK_TRIGGER_FLAG_KILL_AT_DURATION_END = 0x2
178
-
179
- # The task trigger is disabled
180
- TASK_TRIGGER_FLAG_DISABLED = 0x4
181
-
182
- # :stopdoc:
183
-
184
- TASK_MAX_RUN_TIMES = 1440
185
- TASKS_TO_RETRIEVE = 5
186
-
187
- # Task creation
188
-
189
- TASK_VALIDATE_ONLY = 0x1
190
- TASK_CREATE = 0x2
191
- TASK_UPDATE = 0x4
192
- TASK_CREATE_OR_UPDATE = 0x6
193
- TASK_DISABLE = 0x8
194
- TASK_DONT_ADD_PRINCIPAL_ACE = 0x10
195
- TASK_IGNORE_REGISTRATION_TRIGGERS = 0x20
196
-
197
- # Task logon types
198
-
199
- TASK_LOGON_NONE = 0
200
- TASK_LOGON_PASSWORD = 1
201
- TASK_LOGON_S4U = 2
202
- TASK_LOGON_INTERACTIVE_TOKEN = 3
203
- TASK_LOGON_GROUP = 4
204
- TASK_LOGON_SERVICE_ACCOUNT = 5
205
- TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD = 6
206
-
207
- # Priority classes
208
-
209
- REALTIME_PRIORITY_CLASS = 0
210
- HIGH_PRIORITY_CLASS = 1
211
- ABOVE_NORMAL_PRIORITY_CLASS = 2 # Or 3
212
- NORMAL_PRIORITY_CLASS = 4 # Or 5, 6
213
- BELOW_NORMAL_PRIORITY_CLASS = 7 # Or 8
214
- IDLE_PRIORITY_CLASS = 9 # Or 10
215
-
216
- CLSCTX_INPROC_SERVER = 0x1
217
- CLSID_CTask = [0x148BD520,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
218
- CLSID_CTaskScheduler = [0x148BD52A,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
219
- IID_ITaskScheduler = [0x148BD527,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
220
- IID_ITask = [0x148BD524,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
221
- IID_IPersistFile = [0x0000010b,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46].pack('LSSC8')
222
-
223
- # :startdoc:
224
-
225
- attr_accessor :password
226
- attr_reader :host
227
-
228
- # Returns a new TaskScheduler object, attached to +folder+. If that
229
- # folder does not exist, but the +force+ option is set to true, then
230
- # it will be created. Otherwise an error will be raised. The default
231
- # is to use the root folder.
232
- #
233
- # If +task+ and +trigger+ are present, then a new task is generated
234
- # as well. This is effectively the same as .new + #new_work_item.
235
- #
236
- def initialize(task = nil, trigger = nil, folder = "\\", force = false)
237
- @folder = folder
238
- @force = force
239
-
240
- @host = Socket.gethostname
241
- @task = nil
242
- @password = nil
243
-
244
- raise ArgumentError, "invalid folder" unless folder.include?("\\")
245
-
246
- unless [TrueClass, FalseClass].include?(force.class)
247
- raise TypeError, "invalid force value"
248
- end
249
-
250
- begin
251
- @service = WIN32OLE.new('Schedule.Service')
252
- rescue WIN32OLERuntimeError => err
253
- raise Error, err.inspect
254
- end
255
-
256
- @service.Connect
257
-
258
- if folder != "\\"
259
- begin
260
- @root = @service.GetFolder(folder)
261
- rescue WIN32OLERuntimeError => err
262
- if force
263
- @root.CreateFolder(folder)
264
- @root = @service.GetFolder(folder)
265
- else
266
- raise ArgumentError, "folder '#{folder}' not found"
267
- end
268
- end
269
- else
270
- @root = @service.GetFolder(folder)
271
- end
272
-
273
- if task && trigger
274
- new_work_item(task, trigger)
275
- end
276
- end
277
-
278
- # Returns an array of scheduled task names.
279
- #
280
- def enum
281
- # Get the task folder that contains the tasks.
282
- taskCollection = @root.GetTasks(0)
283
-
284
- array = []
285
-
286
- taskCollection.each do |registeredTask|
287
- array << registeredTask.Name
288
- end
289
-
290
- array
291
- end
292
-
293
- alias tasks enum
294
-
295
- # Returns whether or not the specified task exists.
296
- #
297
- def exists?(task)
298
- enum.include?(task)
299
- end
300
-
301
- # Activate the specified task.
302
- #
303
- def activate(task)
304
- raise TypeError unless task.is_a?(String)
305
-
306
- begin
307
- registeredTask = @root.GetTask(task)
308
- registeredTask.Enabled = 1
309
- @task = registeredTask
310
- rescue WIN32OLERuntimeError => err
311
- raise Error, ole_error('activate', err)
312
- end
313
- end
314
-
315
- # Delete the specified task name.
316
- #
317
- def delete(task)
318
- raise TypeError unless task.is_a?(String)
319
-
320
- begin
321
- @root.DeleteTask(task, 0)
322
- rescue WIN32OLERuntimeError => err
323
- raise Error, ole_error('DeleteTask', err)
324
- end
325
- end
326
-
327
- # Execute the current task.
328
- #
329
- def run
330
- raise Error, 'null task' if @task.nil?
331
-
332
- @task.run(nil)
333
- end
334
-
335
- # This method no longer has any effect. It is a no-op that remains for
336
- # backwards compatibility. It will be removed in 0.4.0.
337
- #
338
- def save(file = nil)
339
- warn DeprecatedMethodWarning, "this method is no longer necessary"
340
- raise Error, 'null task' if @task.nil?
341
- # Do nothing, deprecated.
342
- end
343
-
344
- # Terminate (stop) the current task.
345
- #
346
- def terminate
347
- raise Error, 'null task' if @task.nil?
348
- @task.stop(nil)
349
- end
350
-
351
- alias stop terminate
352
-
353
- # Set the host on which the various TaskScheduler methods will execute.
354
- # This method may require administrative privileges.
355
- #
356
- def machine=(host)
357
- raise TypeError unless host.is_a?(String)
358
-
359
- begin
360
- @service.Connect(host)
361
- rescue WIN32OLERuntimeError => err
362
- raise Error, ole_error('Connect', err)
363
- end
364
-
365
- @host = host
366
- host
367
- end
368
-
369
- # Similar to the TaskScheduler#machine= method, this method also allows
370
- # you to pass a user, domain and password as needed. This method may
371
- # require administrative privileges.
372
- #
373
- def set_machine(host, user = nil, domain = nil, password = nil)
374
- raise TypeError unless host.is_a?(String)
375
-
376
- begin
377
- @service.Connect(host, user, domain, password)
378
- rescue WIN32OLERuntimeError => err
379
- raise Error, ole_error('Connect', err)
380
- end
381
-
382
- @host = host
383
- host
384
- end
385
-
386
- alias host= machine=
387
- alias machine host
388
- alias set_host set_machine
389
-
390
- # Sets the +user+ and +password+ for the given task. If the user and
391
- # password are set properly then true is returned.
392
- #
393
- def set_account_information(user, password)
394
- raise Error, 'No currently active task' if @task.nil?
395
-
396
- raise TypeError unless user.is_a?(String)
397
- raise TypeError unless password.is_a?(String)
398
-
399
- @password = password
400
-
401
- begin
402
- @task = @root.RegisterTaskDefinition(
403
- @task.Path,
404
- @task.Definition,
405
- TASK_CREATE_OR_UPDATE,
406
- user,
407
- password,
408
- TASK_LOGON_PASSWORD
409
- )
410
- rescue WIN32OLERuntimeError => err
411
- raise Error, ole_error('RegisterTaskDefinition', err)
412
- end
413
-
414
- true
415
- end
416
-
417
- # Returns the user associated with the task or nil if no user has yet
418
- # been associated with the task.
419
- #
420
- def account_information
421
- @task.nil? ? nil : @task.Definition.Principal.UserId
422
- end
423
-
424
- # Returns the name of the application associated with the task. If
425
- # no application is associated with the task then nil is returned.
426
- #
427
- def application_name
428
- raise Error, 'No currently active task' if @task.nil?
429
-
430
- app = nil
431
-
432
- @task.Definition.Actions.each do |action|
433
- if action.Type == 0 # TASK_ACTION_EXEC
434
- app = action.Path
435
- break
436
- end
437
- end
438
-
439
- app
440
- end
441
-
442
- # Sets the name of the application associated with the task.
443
- #
444
- def application_name=(app)
445
- raise TypeError unless app.is_a?(String)
446
- raise Error, 'No currently active task' if @task.nil?
447
-
448
- definition = @task.Definition
449
-
450
- definition.Actions.each do |action|
451
- action.Path = app if action.Type == 0
452
- end
453
-
454
- user = definition.Principal.UserId
455
-
456
- @task = @root.RegisterTaskDefinition(
457
- @task.Path,
458
- definition,
459
- TASK_CREATE_OR_UPDATE,
460
- user,
461
- @password,
462
- @password ? TASK_LOGON_PASSWORD : TASK_LOGON_INTERACTIVE_TOKEN
463
- )
464
-
465
- app
466
- end
467
-
468
- # Returns the command line parameters for the task.
469
- #
470
- def parameters
471
- raise Error, 'No currently active task' if @task.nil?
472
-
473
- param = nil
474
-
475
- @task.Definition.Actions.each do |action|
476
- param = action.Arguments if action.Type == 0
477
- end
478
-
479
- param
480
- end
481
-
482
- # Sets the parameters for the task. These parameters are passed as command
483
- # line arguments to the application the task will run. To clear the command
484
- # line parameters set it to an empty string.
485
- #--
486
- # NOTE: Again, it seems the task must be reactivated to be picked up.
487
- #
488
- def parameters=(param)
489
- raise TypeError unless param.is_a?(String)
490
- raise Error, 'No currently active task' if @task.nil?
491
-
492
- definition = @task.Definition
493
- definition.Actions.each do |action|
494
- action.Arguments = param if action.Type == 0
495
- end
496
- user = definition.Principal.UserId
497
-
498
- @task = @root.RegisterTaskDefinition(
499
- @task.Path,
500
- definition,
501
- TASK_CREATE_OR_UPDATE,
502
- user,
503
- @password,
504
- @password ? TASK_LOGON_PASSWORD : TASK_LOGON_INTERACTIVE_TOKEN
505
- )
506
-
507
- param
508
- end
509
-
510
- # Returns the working directory for the task.
511
- #
512
- def working_directory
513
- raise Error,"No currently active task" if @task.nil?
514
-
515
- dir = nil
516
-
517
- @task.Definition.Actions.each do |action|
518
- dir = action.WorkingDirectory if action.Type == 0
519
- end
520
-
521
- dir
522
- end
523
-
524
- # Sets the working directory for the task.
525
- #--
526
- # TODO: Why do I have to reactivate the task to see the change?
527
- #
528
- def working_directory=(dir)
529
- raise Error, 'No currently active task' if @task.nil?
530
- raise TypeError unless dir.is_a?(String)
531
-
532
- definition = @task.Definition
533
-
534
- definition.Actions.each do |action|
535
- action.WorkingDirectory = dir if action.Type == 0
536
- end
537
-
538
- user = definition.Principal.UserId
539
-
540
- @task = @root.RegisterTaskDefinition(
541
- @task.Path,
542
- definition,
543
- TASK_CREATE_OR_UPDATE,
544
- user,
545
- @password,
546
- @password ? TASK_LOGON_PASSWORD : TASK_LOGON_INTERACTIVE_TOKEN
547
- )
548
-
549
- dir
550
- end
551
-
552
- # Returns the task's priority level. Possible values are 'idle',
553
- # 'normal', 'high', 'realtime', 'below_normal', 'above_normal',
554
- # and 'unknown'.
555
- #
556
- def priority
557
- raise Error, 'No currently active task' if @task.nil?
558
-
559
- case @task.Definition.Settings.Priority
560
- when 0
561
- priority = 'critical'
562
- when 1
563
- priority = 'highest'
564
- when 2
565
- priority = 'above_normal'
566
- when 3
567
- priority = 'above_normal'
568
- when 4
569
- priority = 'normal'
570
- when 5
571
- priority = 'normal'
572
- when 6
573
- priority = 'normal'
574
- when 7
575
- priority = 'below_normal'
576
- when 8
577
- priority = 'below_normal'
578
- when 9
579
- priority = 'lowest'
580
- when 10
581
- priority = 'idle'
582
- else
583
- priority = 'unknown'
584
- end
585
-
586
- priority
587
- end
588
-
589
- # Sets the priority of the task. The +priority+ should be a numeric
590
- # priority constant value.
591
- #
592
- def priority=(priority)
593
- raise TypeError unless priority.is_a?(Numeric)
594
- raise Error, 'No currently active task' if @task.nil?
595
-
596
- definition = @task.Definition
597
-
598
- begin
599
- definition.Settings.Priority = priority
600
- user = definition.Principal.UserId
601
- rescue WIN32OLERuntimeError => err
602
- raise Error, ole_error('Priority', err)
603
- end
604
-
605
- @task = @root.RegisterTaskDefinition(
606
- @task.Path,
607
- definition,
608
- TASK_CREATE_OR_UPDATE,
609
- user,
610
- @password,
611
- @password ? TASK_LOGON_PASSWORD : TASK_LOGON_INTERACTIVE_TOKEN
612
- )
613
-
614
- priority
615
- end
616
-
617
- # Creates a new work item (scheduled job) with the given +trigger+. The
618
- # trigger variable is a hash of options that define when the scheduled
619
- # job should run.
620
- #
621
- def new_work_item(task, trigger)
622
- raise TypeError unless task.is_a?(String)
623
- raise TypeError unless trigger.is_a?(Hash)
624
-
625
- validate_trigger(trigger)
626
-
627
- taskDefinition = @service.NewTask(0)
628
- taskDefinition.RegistrationInfo.Description = ''
629
- taskDefinition.RegistrationInfo.Author = ''
630
- taskDefinition.Settings.StartWhenAvailable = true
631
- taskDefinition.Settings.Enabled = true
632
- taskDefinition.Settings.Hidden = false
633
-
634
- case trigger[:trigger_type]
635
- when TASK_TIME_TRIGGER_ONCE
636
- type = 1
637
- when TASK_TIME_TRIGGER_DAILY
638
- type = 2
639
- when TASK_TIME_TRIGGER_WEEKLY
640
- type = 3
641
- when TASK_TIME_TRIGGER_MONTHLYDATE
642
- type = 4
643
- when TASK_TIME_TRIGGER_MONTHLYDOW
644
- type = 5
645
- when TASK_EVENT_TRIGGER_ON_IDLE
646
- type = 6
647
- when TASK_EVENT_TRIGGER_AT_SYSTEMSTART
648
- type = 8
649
- when TASK_EVENT_TRIGGER_AT_LOGON
650
- type = 9
651
- else
652
- raise ArgumentError, 'Unknown trigger type'
653
- end
654
-
655
- startTime = "%04d-%02d-%02dT%02d:%02d:00" % [
656
- trigger[:start_year], trigger[:start_month], trigger[:start_day],
657
- trigger[:start_hour], trigger[:start_minute]
658
- ]
659
-
660
- # Set defaults
661
- trigger[:end_year] ||= 0
662
- trigger[:end_month] ||= 0
663
- trigger[:end_day] ||= 0
664
-
665
- endTime = "%04d-%02d-%02dT00:00:00" % [
666
- trigger[:end_year], trigger[:end_month], trigger[:end_day]
667
- ]
668
-
669
- trig = taskDefinition.Triggers.Create(type)
670
- trig.Id = "RegistrationTriggerId#{taskDefinition.Triggers.Count}"
671
- trig.StartBoundary = startTime
672
- trig.EndBoundary = endTime if endTime != '0000-00-00T00:00:00'
673
- trig.Enabled = true
674
-
675
- repetitionPattern = trig.Repetition
676
-
677
- if trigger[:minutes_duration].to_i > 0
678
- repetitionPattern.Duration = "PT#{trigger[:minutes_duration]||0}M"
679
- end
680
-
681
- if trigger[:minutes_interval].to_i > 0
682
- repetitionPattern.Interval = "PT#{trigger[:minutes_interval]||0}M"
683
- end
684
-
685
- tmp = trigger[:type]
686
- tmp = nil unless tmp.is_a?(Hash)
687
-
688
- case trigger[:trigger_type]
689
- when TASK_TIME_TRIGGER_DAILY
690
- trig.DaysInterval = tmp[:days_interval] if tmp && tmp[:days_interval]
691
- if trigger[:random_minutes_interval].to_i > 0
692
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]}M"
693
- end
694
- when TASK_TIME_TRIGGER_WEEKLY
695
- trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
696
- trig.WeeksInterval = tmp[:weeks_interval] if tmp && tmp[:weeks_interval]
697
- if trigger[:random_minutes_interval].to_i > 0
698
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
699
- end
700
- when TASK_TIME_TRIGGER_MONTHLYDATE
701
- trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
702
- trig.DaysOfMonth = tmp[:days] if tmp && tmp[:days]
703
- if trigger[:random_minutes_interval].to_i > 0
704
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
705
- end
706
- when TASK_TIME_TRIGGER_MONTHLYDOW
707
- trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
708
- trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
709
- trig.WeeksOfMonth = tmp[:weeks] if tmp && tmp[:weeks]
710
- if trigger[:random_minutes_interval].to_i>0
711
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
712
- end
713
- when TASK_TIME_TRIGGER_ONCE
714
- if trigger[:random_minutes_interval].to_i > 0
715
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
716
- end
717
- end
718
-
719
- act = taskDefinition.Actions.Create(0)
720
- act.Path = 'cmd'
721
-
722
- begin
723
- @task = @root.RegisterTaskDefinition(
724
- task,
725
- taskDefinition,
726
- TASK_CREATE_OR_UPDATE,
727
- nil,
728
- nil,
729
- TASK_LOGON_INTERACTIVE_TOKEN
730
- )
731
- rescue WIN32OLERuntimeError => err
732
- raise Error, ole_error('RegisterTaskDefinition', err)
733
- end
734
-
735
- @task = @root.GetTask(task)
736
- end
737
-
738
- alias new_task new_work_item
739
-
740
- # Returns the number of triggers associated with the active task.
741
- #
742
- def trigger_count
743
- raise Error, "No currently active task" if @task.nil?
744
-
745
- @task.Definition.Triggers.Count
746
- end
747
-
748
- # Returns a string that describes the current trigger at the specified
749
- # index for the active task.
750
- #
751
- # Example: "At 7:14 AM every day, starting 4/11/2015"
752
- #
753
- def trigger_string(index)
754
- raise TypeError unless index.is_a?(Numeric)
755
- raise Error, 'No currently active task' if @task.nil?
756
- index += 1 # first item index is 1
757
-
758
- begin
759
- trigger = @task.Definition.Triggers.Item(index)
760
- rescue WIN32OLERuntimeError
761
- raise Error, "No trigger found at index '#{index}'"
762
- end
763
-
764
- "Starting #{trigger.StartBoundary}"
765
- end
766
-
767
- # Deletes the trigger at the specified index.
768
- #--
769
- # TODO: Fix.
770
- #
771
- def delete_trigger(index)
772
- raise TypeError unless index.is_a?(Numeric)
773
- raise Error, 'No currently active task' if @task.nil?
774
- index += 1 # first item index is 1
775
-
776
- definition = @task.Definition
777
- definition.Triggers.Remove(index)
778
- user = definition.Principal.UserId
779
-
780
- @task = @root.RegisterTaskDefinition(
781
- @task.Path,
782
- definition,
783
- TASK_CREATE_OR_UPDATE,
784
- user,
785
- @password,
786
- @password ? TASK_LOGON_PASSWORD : TASK_LOGON_INTERACTIVE_TOKEN
787
- )
788
-
789
- index
790
- end
791
-
792
- # Returns a hash that describes the trigger at the given index for the
793
- # current task.
794
- #
795
- def trigger(index)
796
- raise TypeError unless index.is_a?(Numeric)
797
- raise Error, 'No currently active task' if @task.nil?
798
- index += 1 # first item index is 1
799
-
800
- begin
801
- trig = @task.Definition.Triggers.Item(index)
802
- rescue WIN32OLERuntimeError => err
803
- raise Error, ole_error('Item', err)
804
- end
805
-
806
- trigger = {}
807
- trigger[:start_year], trigger[:start_month],
808
- trigger[:start_day], trigger[:start_hour],
809
- trigger[:start_minute] = trig.StartBoundary.scan(/(\d+)-(\d+)-(\d+)T(\d+):(\d+)/).first
810
-
811
- trigger[:end_year], trigger[:end_month],
812
- trigger[:end_day] = trig.StartBoundary.scan(/(\d+)-(\d+)-(\d+)T/).first
813
-
814
- if trig.Repetition.Duration != ""
815
- trigger[:minutes_duration] = trig.Repetition.Duration.scan(/(\d+)M/)[0][0].to_i
816
- end
817
-
818
- if trig.Repetition.Interval != ""
819
- trigger[:minutes_interval] = trig.Repetition.Interval.scan(/(\d+)M/)[0][0].to_i
820
- end
821
-
822
- if trig.RandomDelay != ""
823
- trigger[:random_minutes_interval] = trig.RandomDelay.scan(/(\d+)M/)[0][0].to_i
824
- end
825
-
826
- case trig.Type
827
- when 2
828
- trigger[:trigger_type] = TASK_TIME_TRIGGER_DAILY
829
- tmp = {}
830
- tmp[:days_interval] = trig.DaysInterval
831
- trigger[:type] = tmp
832
- when 3
833
- trigger[:trigger_type] = TASK_TIME_TRIGGER_WEEKLY
834
- tmp = {}
835
- tmp[:weeks_interval] = trig.WeeksInterval
836
- tmp[:days_of_week] = trig.DaysOfWeek
837
- trigger[:type] = tmp
838
- when 4
839
- trigger[:trigger_type] = TASK_TIME_TRIGGER_MONTHLYDATE
840
- tmp = {}
841
- tmp[:months] = trig.MonthsOfYear
842
- tmp[:days] = trig.DaysOfMonth
843
- trigger[:type] = tmp
844
- when 5
845
- trigger[:trigger_type] = TASK_TIME_TRIGGER_MONTHLYDOW
846
- tmp = {}
847
- tmp[:months] = trig.MonthsOfYear
848
- tmp[:days_of_week] = trig.DaysOfWeek
849
- tmp[:weeks] = trig.weeks
850
- trigger[:type] = tmp
851
- when 1
852
- trigger[:trigger_type] = TASK_TIME_TRIGGER_ONCE
853
- tmp = {}
854
- tmp[:once] = nil
855
- trigger[:type] = tmp
856
- else
857
- raise Error, 'Unknown trigger type'
858
- end
859
-
860
- trigger
861
- end
862
-
863
- # Sets the trigger for the currently active task. The +trigger+ is a hash
864
- # with the following possible options:
865
- #
866
- # * days
867
- # * days_interval
868
- # * days_of_week
869
- # * end_day
870
- # * end_month
871
- # * end_year
872
- # * flags
873
- # * minutes_duration
874
- # * minutes_interval
875
- # * months
876
- # * random_minutes_interval
877
- # * start_day
878
- # * start_hour
879
- # * start_minute
880
- # * start_month
881
- # * start_year
882
- # * trigger_type
883
- # * type
884
- # * weeks
885
- # * weeks_interval
886
- #
887
- def trigger=(trigger)
888
- raise TypeError unless trigger.is_a?(Hash)
889
- raise Error, 'No currently active task' if @task.nil?
890
-
891
- validate_trigger(trigger)
892
-
893
- definition = @task.Definition
894
- definition.Triggers.Clear()
895
-
896
- case trigger[:trigger_type]
897
- when TASK_TIME_TRIGGER_ONCE
898
- type = 1
899
- when TASK_TIME_TRIGGER_DAILY
900
- type = 2
901
- when TASK_TIME_TRIGGER_WEEKLY
902
- type = 3
903
- when TASK_TIME_TRIGGER_MONTHLYDATE
904
- type = 4
905
- when TASK_TIME_TRIGGER_MONTHLYDOW
906
- type = 5
907
- when TASK_EVENT_TRIGGER_ON_IDLE
908
- type = 6
909
- when TASK_EVENT_TRIGGER_AT_SYSTEM_START
910
- type = 8
911
- when TASK_EVENT_TRIGGER_AT_LOGON
912
- type = 9
913
- else
914
- raise Error, 'Unknown trigger type'
915
- end
916
-
917
- startTime = "%04d-%02d-%02dT%02d:%02d:00" % [
918
- trigger[:start_year], trigger[:start_month],
919
- trigger[:start_day], trigger[:start_hour], trigger[:start_minute]
920
- ]
921
-
922
- endTime = "%04d-%02d-%02dT00:00:00" % [
923
- trigger[:end_year], trigger[:end_month], trigger[:end_day]
924
- ]
925
-
926
- trig = definition.Triggers.Create(type)
927
- trig.Id = "RegistrationTriggerId#{definition.Triggers.Count}"
928
- trig.StartBoundary = startTime
929
- trig.EndBoundary = endTime if endTime != '0000-00-00T00:00:00'
930
- trig.Enabled = true
931
-
932
- repetitionPattern = trig.Repetition
933
-
934
- if trigger[:minutes_duration].to_i > 0
935
- repetitionPattern.Duration = "PT#{trigger[:minutes_duration]||0}M"
936
- end
937
-
938
- if trigger[:minutes_interval].to_i > 0
939
- repetitionPattern.Interval = "PT#{trigger[:minutes_interval]||0}M"
940
- end
941
-
942
- tmp = trigger[:type]
943
- tmp = nil unless tmp.is_a?(Hash)
944
-
945
- case trigger[:trigger_type]
946
- when TASK_TIME_TRIGGER_DAILY
947
- trig.DaysInterval = tmp[:days_interval] if tmp && tmp[:days_interval]
948
- if trigger[:random_minutes_interval].to_i > 0
949
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]}M"
950
- end
951
- when TASK_TIME_TRIGGER_WEEKLY
952
- trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
953
- trig.WeeksInterval = tmp[:weeks_interval] if tmp && tmp[:weeks_interval]
954
- if trigger[:random_minutes_interval].to_i > 0
955
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
956
- end
957
- when TASK_TIME_TRIGGER_MONTHLYDATE
958
- trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
959
- trig.DaysOfMonth = tmp[:days] if tmp && tmp[:days]
960
- if trigger[:random_minutes_interval].to_i > 0
961
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
962
- end
963
- when TASK_TIME_TRIGGER_MONTHLYDOW
964
- trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
965
- trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
966
- trig.WeeksOfMonth = tmp[:weeks] if tmp && tmp[:weeks]
967
- if trigger[:random_minutes_interval].to_i > 0
968
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
969
- end
970
- when TASK_TIME_TRIGGER_ONCE
971
- if trigger[:random_minutes_interval].to_i > 0
972
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
973
- end
974
- end
975
-
976
- user = definition.Principal.UserId
977
-
978
- @task = @root.RegisterTaskDefinition(
979
- @task.Path,
980
- definition,
981
- TASK_CREATE_OR_UPDATE,
982
- user,
983
- @password,
984
- @password ? TASK_LOGON_PASSWORD : TASK_LOGON_INTERACTIVE_TOKEN
985
- )
986
-
987
- trigger
988
- end
989
-
990
- # Adds a trigger at the specified index.
991
- #
992
- def add_trigger(index, trigger)
993
- raise TypeError unless index.is_a?(Numeric)
994
- raise TypeError unless trigger.is_a?(Hash)
995
- raise Error, 'No currently active task' if @task.nil?
996
-
997
- definition = @task.Definition
998
- case trigger[:trigger_type]
999
- when TASK_TIME_TRIGGER_DAILY
1000
- type = 2
1001
- when TASK_TIME_TRIGGER_WEEKLY
1002
- type = 3
1003
- when TASK_TIME_TRIGGER_MONTHLYDATE
1004
- type = 4
1005
- when TASK_TIME_TRIGGER_MONTHLYDOW
1006
- type = 5
1007
- when TASK_TIME_TRIGGER_ONCE
1008
- type = 1
1009
- else
1010
- raise Error, 'Unknown trigger type'
1011
- end
1012
-
1013
- startTime = "%04d-%02d-%02dT%02d:%02d:00" % [
1014
- trigger[:start_year], trigger[:start_month], trigger[:start_day],
1015
- trigger[:start_hour], trigger[:start_minute]
1016
- ]
1017
-
1018
- # Set defaults
1019
- trigger[:end_year] ||= 0
1020
- trigger[:end_month] ||= 0
1021
- trigger[:end_day] ||= 0
1022
-
1023
- endTime = "%04d-%02d-%02dT00:00:00" % [
1024
- trigger[:end_year], trigger[:end_month], trigger[:end_day]
1025
- ]
1026
-
1027
- trig = definition.Triggers.Create(type)
1028
- trig.Id = "RegistrationTriggerId#{definition.Triggers.Count}"
1029
- trig.StartBoundary = startTime
1030
- trig.EndBoundary = endTime if endTime != '0000-00-00T00:00:00'
1031
- trig.Enabled = true
1032
-
1033
- repetitionPattern = trig.Repetition
1034
-
1035
- if trigger[:minutes_duration].to_i > 0
1036
- repetitionPattern.Duration = "PT#{trigger[:minutes_duration]||0}M"
1037
- end
1038
-
1039
- if trigger[:minutes_interval].to_i > 0
1040
- repetitionPattern.Interval = "PT#{trigger[:minutes_interval]||0}M"
1041
- end
1042
-
1043
- tmp = trigger[:type]
1044
- tmp = nil unless tmp.is_a?(Hash)
1045
-
1046
- case trigger[:trigger_type]
1047
- when TASK_TIME_TRIGGER_DAILY
1048
- trig.DaysInterval = tmp[:days_interval] if tmp && tmp[:days_interval]
1049
- if trigger[:random_minutes_interval].to_i > 0
1050
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]}M"
1051
- end
1052
- when TASK_TIME_TRIGGER_WEEKLY
1053
- trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
1054
- trig.WeeksInterval = tmp[:weeks_interval] if tmp && tmp[:weeks_interval]
1055
- if trigger[:random_minutes_interval].to_i > 0
1056
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
1057
- end
1058
- when TASK_TIME_TRIGGER_MONTHLYDATE
1059
- trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
1060
- trig.DaysOfMonth = tmp[:days] if tmp && tmp[:days]
1061
- if trigger[:random_minutes_interval].to_i > 0
1062
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
1063
- end
1064
- when TASK_TIME_TRIGGER_MONTHLYDOW
1065
- trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
1066
- trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
1067
- trig.WeeksOfMonth = tmp[:weeks] if tmp && tmp[:weeks]
1068
- if trigger[:random_minutes_interval].to_i > 0
1069
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
1070
- end
1071
- when TASK_TIME_TRIGGER_ONCE
1072
- if trigger[:random_minutes_interval].to_i > 0
1073
- trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
1074
- end
1075
- end
1076
-
1077
- user = definition.Principal.UserId
1078
-
1079
- begin
1080
-
1081
- @task = @root.RegisterTaskDefinition(
1082
- @task.Path,
1083
- definition,
1084
- TASK_CREATE_OR_UPDATE,
1085
- user,
1086
- @password,
1087
- @password ? TASK_LOGON_PASSWORD : TASK_LOGON_INTERACTIVE_TOKEN
1088
- )
1089
- rescue WIN32OLERuntimeError => err
1090
- raise Error, ole_error('add_trigger', err)
1091
- end
1092
-
1093
- true
1094
- end
1095
-
1096
- # Returns the status of the currently active task. Possible values are
1097
- # 'ready', 'running', 'not scheduled' or 'unknown'.
1098
- #
1099
- def status
1100
- raise Error, 'No currently active task' if @task.nil?
1101
-
1102
- case @task.State
1103
- when 3
1104
- status = 'ready'
1105
- when 4
1106
- status = 'running'
1107
- when 1
1108
- status = 'not scheduled'
1109
- else
1110
- status = 'unknown'
1111
- end
1112
-
1113
- status
1114
- end
1115
-
1116
- # Returns the exit code from the last scheduled run.
1117
- #
1118
- def exit_code
1119
- raise Error, 'No currently active task' if @task.nil?
1120
-
1121
- @task.LastTaskResult
1122
- end
1123
-
1124
- # Returns the comment associated with the task, if any.
1125
- #
1126
- def comment
1127
- raise Error, 'No currently active task' if @task.nil?
1128
-
1129
- @task.Definition.RegistrationInfo.Description
1130
- end
1131
-
1132
- # Sets the comment for the task.
1133
- #
1134
- def comment=(comment)
1135
- raise TypeError unless comment.is_a?(String)
1136
- raise Error, 'No currently active task' if @task.nil?
1137
-
1138
- definition = @task.Definition
1139
- definition.RegistrationInfo.Description = comment
1140
-
1141
- user = definition.Principal.UserId
1142
-
1143
- @task = @root.RegisterTaskDefinition(
1144
- @task.Path,
1145
- definition,
1146
- TASK_CREATE_OR_UPDATE,
1147
- user,
1148
- @password,
1149
- @password ? 1 : 3
1150
- )
1151
-
1152
- comment
1153
- end
1154
-
1155
- # Returns the name of the user who created the task.
1156
- #
1157
- def creator
1158
- raise Error, 'No currently active task' if @task.nil?
1159
-
1160
- @task.Definition.RegistrationInfo.Author
1161
- end
1162
-
1163
- alias author creator
1164
-
1165
- # Sets the creator for the task.
1166
- #
1167
- def creator=(creator)
1168
- raise TypeError unless creator.is_a?(String)
1169
- raise Error, 'No currently active task' if @task.nil?
1170
-
1171
- definition = @task.Definition
1172
- definition.RegistrationInfo.Author = creator
1173
-
1174
- user = definition.Principal.UserId
1175
-
1176
- @task = @root.RegisterTaskDefinition(
1177
- @task.Path,
1178
- definition,
1179
- TASK_CREATE_OR_UPDATE,
1180
- user,
1181
- @password,
1182
- @password ? TASK_LOGON_PASSWORD : TASK_LOGON_INTERACTIVE_TOKEN
1183
- )
1184
-
1185
- creator
1186
- end
1187
-
1188
- # Returns a Time object that indicates the next time the task will run.
1189
- #
1190
- def next_run_time
1191
- raise Error, 'No currently active task' if @task.nil?
1192
-
1193
- @task.NextRunTime
1194
- end
1195
-
1196
- # Returns a Time object indicating the most recent time the task ran or
1197
- # nil if the task has never run.
1198
- #
1199
- def most_recent_run_time
1200
- raise Error, 'No currently active task' if @task.nil?
1201
-
1202
- time = nil
1203
-
1204
- begin
1205
- time = Time.parse(@task.LastRunTime)
1206
- rescue
1207
- # Ignore
1208
- end
1209
-
1210
- time
1211
- end
1212
-
1213
- # Returns the maximum length of time, in milliseconds, that the task
1214
- # will run before terminating.
1215
- #
1216
- def max_run_time
1217
- raise Error, 'No currently active task' if @task.nil?
1218
-
1219
- t = @task.Definition.Settings.ExecutionTimeLimit
1220
- year = t.scan(/(\d+?)Y/).flatten.first
1221
- month = t.scan(/(\d+?)M/).flatten.first
1222
- day = t.scan(/(\d+?)D/).flatten.first
1223
- hour = t.scan(/(\d+?)H/).flatten.first
1224
- min = t.scan(/T.*(\d+?)M/).flatten.first
1225
- sec = t.scan(/(\d+?)S/).flatten.first
1226
-
1227
- time = 0
1228
- time += year.to_i * 365 if year
1229
- time += month.to_i * 30 if month
1230
- time += day.to_i if day
1231
- time *= 24
1232
- time += hour.to_i if hour
1233
- time *= 60
1234
- time += min.to_i if min
1235
- time *= 60
1236
- time += sec.to_i if sec
1237
- time *= 1000
1238
-
1239
- time
1240
- end
1241
-
1242
- # Sets the maximum length of time, in milliseconds, that the task can run
1243
- # before terminating. Returns the value you specified if successful.
1244
- #
1245
- def max_run_time=(max_run_time)
1246
- raise TypeError unless max_run_time.is_a?(Numeric)
1247
- raise Error, 'No currently active task' if @task.nil?
1248
-
1249
- t = max_run_time
1250
- t /= 1000
1251
- limit ="PT#{t}S"
1252
-
1253
- definition = @task.Definition
1254
- definition.Settings.ExecutionTimeLimit = limit
1255
- user = definition.Principal.UserId
1256
-
1257
- @task = @root.RegisterTaskDefinition(
1258
- @task.Path,
1259
- definition,
1260
- TASK_CREATE_OR_UPDATE,
1261
- user,
1262
- @password,
1263
- @password ? TASK_LOGON_PASSWORD : TASK_LOGON_INTERACTIVE_TOKEN
1264
- )
1265
-
1266
- max_run_time
1267
- end
1268
-
1269
- # Shorthand constants
1270
-
1271
- IDLE = IDLE_PRIORITY_CLASS
1272
- NORMAL = NORMAL_PRIORITY_CLASS
1273
- HIGH = HIGH_PRIORITY_CLASS
1274
- REALTIME = REALTIME_PRIORITY_CLASS
1275
- BELOW_NORMAL = BELOW_NORMAL_PRIORITY_CLASS
1276
- ABOVE_NORMAL = ABOVE_NORMAL_PRIORITY_CLASS
1277
-
1278
- ONCE = TASK_TIME_TRIGGER_ONCE
1279
- DAILY = TASK_TIME_TRIGGER_DAILY
1280
- WEEKLY = TASK_TIME_TRIGGER_WEEKLY
1281
- MONTHLYDATE = TASK_TIME_TRIGGER_MONTHLYDATE
1282
- MONTHLYDOW = TASK_TIME_TRIGGER_MONTHLYDOW
1283
-
1284
- ON_IDLE = TASK_EVENT_TRIGGER_ON_IDLE
1285
- AT_SYSTEMSTART = TASK_EVENT_TRIGGER_AT_SYSTEMSTART
1286
- AT_LOGON = TASK_EVENT_TRIGGER_AT_LOGON
1287
- FIRST_WEEK = TASK_FIRST_WEEK
1288
- SECOND_WEEK = TASK_SECOND_WEEK
1289
- THIRD_WEEK = TASK_THIRD_WEEK
1290
- FOURTH_WEEK = TASK_FOURTH_WEEK
1291
- LAST_WEEK = TASK_LAST_WEEK
1292
- SUNDAY = TASK_SUNDAY
1293
- MONDAY = TASK_MONDAY
1294
- TUESDAY = TASK_TUESDAY
1295
- WEDNESDAY = TASK_WEDNESDAY
1296
- THURSDAY = TASK_THURSDAY
1297
- FRIDAY = TASK_FRIDAY
1298
- SATURDAY = TASK_SATURDAY
1299
- JANUARY = TASK_JANUARY
1300
- FEBRUARY = TASK_FEBRUARY
1301
- MARCH = TASK_MARCH
1302
- APRIL = TASK_APRIL
1303
- MAY = TASK_MAY
1304
- JUNE = TASK_JUNE
1305
- JULY = TASK_JULY
1306
- AUGUST = TASK_AUGUST
1307
- SEPTEMBER = TASK_SEPTEMBER
1308
- OCTOBER = TASK_OCTOBER
1309
- NOVEMBER = TASK_NOVEMBER
1310
- DECEMBER = TASK_DECEMBER
1311
-
1312
- INTERACTIVE = TASK_FLAG_INTERACTIVE
1313
- DELETE_WHEN_DONE = TASK_FLAG_DELETE_WHEN_DONE
1314
- DISABLED = TASK_FLAG_DISABLED
1315
- START_ONLY_IF_IDLE = TASK_FLAG_START_ONLY_IF_IDLE
1316
- KILL_ON_IDLE_END = TASK_FLAG_KILL_ON_IDLE_END
1317
- DONT_START_IF_ON_BATTERIES = TASK_FLAG_DONT_START_IF_ON_BATTERIES
1318
- KILL_IF_GOING_ON_BATTERIES = TASK_FLAG_KILL_IF_GOING_ON_BATTERIES
1319
- RUN_ONLY_IF_DOCKED = TASK_FLAG_RUN_ONLY_IF_DOCKED
1320
- HIDDEN = TASK_FLAG_HIDDEN
1321
- RUN_IF_CONNECTED_TO_INTERNET = TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET
1322
- RESTART_ON_IDLE_RESUME = TASK_FLAG_RESTART_ON_IDLE_RESUME
1323
- SYSTEM_REQUIRED = TASK_FLAG_SYSTEM_REQUIRED
1324
- RUN_ONLY_IF_LOGGED_ON = TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
1325
-
1326
- FLAG_HAS_END_DATE = TASK_TRIGGER_FLAG_HAS_END_DATE
1327
- FLAG_KILL_AT_DURATION_END = TASK_TRIGGER_FLAG_KILL_AT_DURATION_END
1328
- FLAG_DISABLED = TASK_TRIGGER_FLAG_DISABLED
1329
-
1330
- MAX_RUN_TIMES = TASK_MAX_RUN_TIMES
1331
-
1332
- private
1333
-
1334
- def validate_trigger(hash)
1335
- [:start_year, :start_month, :start_day].each{ |key|
1336
- raise ArgumentError, "#{key} must be set" unless hash[key]
1337
- }
1338
- end
1339
- end
1340
- end
1341
-
1342
- if $0 == __FILE__
1343
- require 'socket'
1344
- include Win32
1345
-
1346
- task = 'foo'
1347
- ts = TaskScheduler.new
1348
-
1349
- trigger = {
1350
- :start_year => 2015,
1351
- :start_month => 4,
1352
- :start_day => 25,
1353
- :start_hour => 23,
1354
- :start_minute => 5,
1355
- :trigger_type => TaskScheduler::AT_SYSTEMSTART, # Need admin privs
1356
- :type => {
1357
- :weeks => TaskScheduler::FIRST_WEEK | TaskScheduler::LAST_WEEK,
1358
- :days_of_week => TaskScheduler::MONDAY | TaskScheduler::FRIDAY,
1359
- :months => TaskScheduler::APRIL | TaskScheduler::MAY
1360
- }
1361
- }
1362
-
1363
- ts.new_task(task, trigger)
1364
- ts.activate(task)
1365
- #p ts.account_information
1366
- #ts.save
1367
- #ts.machine = Socket.gethostname
1368
- end
1
+ require_relative 'windows/helper'
2
+ require 'win32ole'
3
+ require 'socket'
4
+ require 'time'
5
+ require 'structured_warnings'
6
+
7
+ # The Win32 module serves as a namespace only
8
+ module Win32
9
+
10
+ # The TaskScheduler class encapsulates a Windows scheduled task
11
+ class TaskScheduler
12
+ include Windows::TaskSchedulerHelper
13
+
14
+ # The version of the win32-taskscheduler library
15
+ VERSION = '0.3.2'.freeze
16
+
17
+ # The Error class is typically raised if any TaskScheduler methods fail.
18
+ class Error < StandardError; end
19
+
20
+ # Triggers
21
+
22
+ # Trigger is set to run the task a single tim
23
+ TASK_TIME_TRIGGER_ONCE = 0
24
+
25
+ # Trigger is set to run the task on a daily interval
26
+ TASK_TIME_TRIGGER_DAILY = 1
27
+
28
+ # Trigger is set to run the task on specific days of a specific week & month
29
+ TASK_TIME_TRIGGER_WEEKLY = 2
30
+
31
+ # Trigger is set to run the task on specific day(s) of the month
32
+ TASK_TIME_TRIGGER_MONTHLYDATE = 3
33
+
34
+ # Trigger is set to run the task on specific day(s) of the month
35
+ TASK_TIME_TRIGGER_MONTHLYDOW = 4
36
+
37
+ # Trigger is set to run the task if the system remains idle for the amount
38
+ # of time specified by the idle wait time of the task
39
+ TASK_EVENT_TRIGGER_ON_IDLE = 5
40
+
41
+ # Trigger is set to run the task at system startup
42
+ TASK_EVENT_TRIGGER_AT_SYSTEMSTART = 6
43
+
44
+ # Trigger is set to run the task when a user logs on
45
+ TASK_EVENT_TRIGGER_AT_LOGON = 7
46
+
47
+ # Daily Tasks
48
+
49
+ # The task will run on Sunday
50
+ TASK_SUNDAY = 0x1
51
+
52
+ # The task will run on Monday
53
+ TASK_MONDAY = 0x2
54
+
55
+ # The task will run on Tuesday
56
+ TASK_TUESDAY = 0x4
57
+
58
+ # The task will run on Wednesday
59
+ TASK_WEDNESDAY = 0x8
60
+
61
+ # The task will run on Thursday
62
+ TASK_THURSDAY = 0x10
63
+
64
+ # The task will run on Friday
65
+ TASK_FRIDAY = 0x20
66
+
67
+ # The task will run on Saturday
68
+ TASK_SATURDAY = 0x40
69
+
70
+ # Weekly tasks
71
+
72
+ # The task will run between the 1st and 7th day of the month
73
+ TASK_FIRST_WEEK = 1
74
+
75
+ # The task will run between the 8th and 14th day of the month
76
+ TASK_SECOND_WEEK = 2
77
+
78
+ # The task will run between the 15th and 21st day of the month
79
+ TASK_THIRD_WEEK = 3
80
+
81
+ # The task will run between the 22nd and 28th day of the month
82
+ TASK_FOURTH_WEEK = 4
83
+
84
+ # The task will run the last seven days of the month
85
+ TASK_LAST_WEEK = 5
86
+
87
+ # Monthly tasks
88
+
89
+ # The task will run in January
90
+ TASK_JANUARY = 0x1
91
+
92
+ # The task will run in February
93
+ TASK_FEBRUARY = 0x2
94
+
95
+ # The task will run in March
96
+ TASK_MARCH = 0x4
97
+
98
+ # The task will run in April
99
+ TASK_APRIL = 0x8
100
+
101
+ # The task will run in May
102
+ TASK_MAY = 0x10
103
+
104
+ # The task will run in June
105
+ TASK_JUNE = 0x20
106
+
107
+ # The task will run in July
108
+ TASK_JULY = 0x40
109
+
110
+ # The task will run in August
111
+ TASK_AUGUST = 0x80
112
+
113
+ # The task will run in September
114
+ TASK_SEPTEMBER = 0x100
115
+
116
+ # The task will run in October
117
+ TASK_OCTOBER = 0x200
118
+
119
+ # The task will run in November
120
+ TASK_NOVEMBER = 0x400
121
+
122
+ # The task will run in December
123
+ TASK_DECEMBER = 0x800
124
+
125
+ # Flags
126
+
127
+ # Used when converting AT service jobs into work items
128
+ TASK_FLAG_INTERACTIVE = 0x1
129
+
130
+ # The work item will be deleted when there are no more scheduled run times
131
+ TASK_FLAG_DELETE_WHEN_DONE = 0x2
132
+
133
+ # The work item is disabled. Useful for temporarily disabling a task
134
+ TASK_FLAG_DISABLED = 0x4
135
+
136
+ # The work item begins only if the computer is not in use at the scheduled
137
+ # start time
138
+ TASK_FLAG_START_ONLY_IF_IDLE = 0x10
139
+
140
+ # The work item terminates if the computer makes an idle to non-idle
141
+ # transition while the work item is running
142
+ TASK_FLAG_KILL_ON_IDLE_END = 0x20
143
+
144
+ # The work item does not start if the computer is running on battery power
145
+ TASK_FLAG_DONT_START_IF_ON_BATTERIES = 0x40
146
+
147
+ # The work item ends, and the associated application quits, if the computer
148
+ # switches to battery power
149
+ TASK_FLAG_KILL_IF_GOING_ON_BATTERIES = 0x80
150
+
151
+ # The work item starts only if the computer is in a docking station
152
+ TASK_FLAG_RUN_ONLY_IF_DOCKED = 0x100
153
+
154
+ # The work item created will be hidden
155
+ TASK_FLAG_HIDDEN = 0x200
156
+
157
+ # The work item runs only if there is a valid internet connection
158
+ TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET = 0x400
159
+
160
+ # The work item starts again if the computer makes a non-idle to idle
161
+ # transition
162
+ TASK_FLAG_RESTART_ON_IDLE_RESUME = 0x800
163
+
164
+ # The work item causes the system to be resumed, or awakened, if the
165
+ # system is running on batter power
166
+ TASK_FLAG_SYSTEM_REQUIRED = 0x1000
167
+
168
+ # The work item runs only if a specified account is logged on interactively
169
+ TASK_FLAG_RUN_ONLY_IF_LOGGED_ON = 0x2000
170
+
171
+ # Triggers
172
+
173
+ # The task will stop at some point in time
174
+ TASK_TRIGGER_FLAG_HAS_END_DATE = 0x1
175
+
176
+ # The task can be stopped at the end of the repetition period
177
+ TASK_TRIGGER_FLAG_KILL_AT_DURATION_END = 0x2
178
+
179
+ # The task trigger is disabled
180
+ TASK_TRIGGER_FLAG_DISABLED = 0x4
181
+
182
+ # :stopdoc:
183
+
184
+ TASK_MAX_RUN_TIMES = 1440
185
+ TASKS_TO_RETRIEVE = 5
186
+
187
+ # Task creation
188
+
189
+ TASK_VALIDATE_ONLY = 0x1
190
+ TASK_CREATE = 0x2
191
+ TASK_UPDATE = 0x4
192
+ TASK_CREATE_OR_UPDATE = 0x6
193
+ TASK_DISABLE = 0x8
194
+ TASK_DONT_ADD_PRINCIPAL_ACE = 0x10
195
+ TASK_IGNORE_REGISTRATION_TRIGGERS = 0x20
196
+
197
+ # Task logon types
198
+
199
+ TASK_LOGON_NONE = 0
200
+ TASK_LOGON_PASSWORD = 1
201
+ TASK_LOGON_S4U = 2
202
+ TASK_LOGON_INTERACTIVE_TOKEN = 3
203
+ TASK_LOGON_GROUP = 4
204
+ TASK_LOGON_SERVICE_ACCOUNT = 5
205
+ TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD = 6
206
+
207
+ # Priority classes
208
+
209
+ REALTIME_PRIORITY_CLASS = 0
210
+ HIGH_PRIORITY_CLASS = 1
211
+ ABOVE_NORMAL_PRIORITY_CLASS = 2 # Or 3
212
+ NORMAL_PRIORITY_CLASS = 4 # Or 5, 6
213
+ BELOW_NORMAL_PRIORITY_CLASS = 7 # Or 8
214
+ IDLE_PRIORITY_CLASS = 9 # Or 10
215
+
216
+ CLSCTX_INPROC_SERVER = 0x1
217
+ CLSID_CTask = [0x148BD520,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
218
+ CLSID_CTaskScheduler = [0x148BD52A,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
219
+ IID_ITaskScheduler = [0x148BD527,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
220
+ IID_ITask = [0x148BD524,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
221
+ IID_IPersistFile = [0x0000010b,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46].pack('LSSC8')
222
+
223
+ # :startdoc:
224
+
225
+ attr_accessor :password
226
+ attr_reader :host
227
+
228
+ # Returns a new TaskScheduler object, attached to +folder+. If that
229
+ # folder does not exist, but the +force+ option is set to true, then
230
+ # it will be created. Otherwise an error will be raised. The default
231
+ # is to use the root folder.
232
+ #
233
+ # If +task+ and +trigger+ are present, then a new task is generated
234
+ # as well. This is effectively the same as .new + #new_work_item.
235
+ #
236
+ def initialize(task = nil, trigger = nil, folder = "\\", force = false)
237
+ @folder = folder
238
+ @force = force
239
+
240
+ @host = Socket.gethostname
241
+ @task = nil
242
+ @password = nil
243
+
244
+ raise ArgumentError, "invalid folder" unless folder.include?("\\")
245
+
246
+ unless [TrueClass, FalseClass].include?(force.class)
247
+ raise TypeError, "invalid force value"
248
+ end
249
+
250
+ begin
251
+ @service = WIN32OLE.new('Schedule.Service')
252
+ rescue WIN32OLERuntimeError => err
253
+ raise Error, err.inspect
254
+ end
255
+
256
+ @service.Connect
257
+
258
+ if folder != "\\"
259
+ begin
260
+ @root = @service.GetFolder(folder)
261
+ rescue WIN32OLERuntimeError => err
262
+ if force
263
+ @root.CreateFolder(folder)
264
+ @root = @service.GetFolder(folder)
265
+ else
266
+ raise ArgumentError, "folder '#{folder}' not found"
267
+ end
268
+ end
269
+ else
270
+ @root = @service.GetFolder(folder)
271
+ end
272
+
273
+ if task && trigger
274
+ new_work_item(task, trigger)
275
+ end
276
+ end
277
+
278
+ # Returns an array of scheduled task names.
279
+ #
280
+ def enum
281
+ # Get the task folder that contains the tasks.
282
+ taskCollection = @root.GetTasks(0)
283
+
284
+ array = []
285
+
286
+ taskCollection.each do |registeredTask|
287
+ array << registeredTask.Name
288
+ end
289
+
290
+ array
291
+ end
292
+
293
+ alias tasks enum
294
+
295
+ # Returns whether or not the specified task exists.
296
+ #
297
+ def exists?(task)
298
+ enum.include?(task)
299
+ end
300
+
301
+ # Activate the specified task.
302
+ #
303
+ def activate(task)
304
+ raise TypeError unless task.is_a?(String)
305
+
306
+ begin
307
+ registeredTask = @root.GetTask(task)
308
+ registeredTask.Enabled = 1
309
+ @task = registeredTask
310
+ rescue WIN32OLERuntimeError => err
311
+ raise Error, ole_error('activate', err)
312
+ end
313
+ end
314
+
315
+ # Delete the specified task name.
316
+ #
317
+ def delete(task)
318
+ raise TypeError unless task.is_a?(String)
319
+
320
+ begin
321
+ @root.DeleteTask(task, 0)
322
+ rescue WIN32OLERuntimeError => err
323
+ raise Error, ole_error('DeleteTask', err)
324
+ end
325
+ end
326
+
327
+ # Execute the current task.
328
+ #
329
+ def run
330
+ check_for_active_task
331
+ @task.run(nil)
332
+ end
333
+
334
+ # This method no longer has any effect. It is a no-op that remains for
335
+ # backwards compatibility. It will be removed in 0.4.0.
336
+ #
337
+ def save(file = nil)
338
+ warn DeprecatedMethodWarning, "this method is no longer necessary"
339
+ check_for_active_task
340
+ # Do nothing, deprecated.
341
+ end
342
+
343
+ # Terminate (stop) the current task.
344
+ #
345
+ def terminate
346
+ check_for_active_task
347
+ @task.stop(nil)
348
+ end
349
+
350
+ alias stop terminate
351
+
352
+ # Set the host on which the various TaskScheduler methods will execute.
353
+ # This method may require administrative privileges.
354
+ #
355
+ def machine=(host)
356
+ raise TypeError unless host.is_a?(String)
357
+
358
+ begin
359
+ @service.Connect(host)
360
+ rescue WIN32OLERuntimeError => err
361
+ raise Error, ole_error('Connect', err)
362
+ end
363
+
364
+ @host = host
365
+ host
366
+ end
367
+
368
+ # Similar to the TaskScheduler#machine= method, this method also allows
369
+ # you to pass a user, domain and password as needed. This method may
370
+ # require administrative privileges.
371
+ #
372
+ def set_machine(host, user = nil, domain = nil, password = nil)
373
+ raise TypeError unless host.is_a?(String)
374
+
375
+ begin
376
+ @service.Connect(host, user, domain, password)
377
+ rescue WIN32OLERuntimeError => err
378
+ raise Error, ole_error('Connect', err)
379
+ end
380
+
381
+ @host = host
382
+ host
383
+ end
384
+
385
+ alias host= machine=
386
+ alias machine host
387
+ alias set_host set_machine
388
+
389
+ # Sets the +user+ and +password+ for the given task. If the user and
390
+ # password are set properly then true is returned.
391
+ #
392
+ def set_account_information(user, password)
393
+ raise TypeError unless user.is_a?(String)
394
+ raise TypeError unless password.is_a?(String)
395
+ check_for_active_task
396
+
397
+ @password = password
398
+
399
+ begin
400
+ @task = @root.RegisterTaskDefinition(
401
+ @task.Path,
402
+ @task.Definition,
403
+ TASK_CREATE_OR_UPDATE,
404
+ user,
405
+ password,
406
+ TASK_LOGON_PASSWORD
407
+ )
408
+ rescue WIN32OLERuntimeError => err
409
+ raise Error, ole_error('RegisterTaskDefinition', err)
410
+ end
411
+
412
+ true
413
+ end
414
+
415
+ # Returns the user associated with the task or nil if no user has yet
416
+ # been associated with the task.
417
+ #
418
+ def account_information
419
+ @task.nil? ? nil : @task.Definition.Principal.UserId
420
+ end
421
+
422
+ # Returns the name of the application associated with the task. If
423
+ # no application is associated with the task then nil is returned.
424
+ #
425
+ def application_name
426
+ check_for_active_task
427
+
428
+ app = nil
429
+
430
+ @task.Definition.Actions.each do |action|
431
+ if action.Type == 0 # TASK_ACTION_EXEC
432
+ app = action.Path
433
+ break
434
+ end
435
+ end
436
+
437
+ app
438
+ end
439
+
440
+ # Sets the name of the application associated with the task.
441
+ #
442
+ def application_name=(app)
443
+ raise TypeError unless app.is_a?(String)
444
+ check_for_active_task
445
+
446
+ definition = @task.Definition
447
+
448
+ definition.Actions.each do |action|
449
+ action.Path = app if action.Type == 0
450
+ end
451
+
452
+ update_task_definition(definition)
453
+
454
+ app
455
+ end
456
+
457
+ # Returns the command line parameters for the task.
458
+ #
459
+ def parameters
460
+ check_for_active_task
461
+
462
+ param = nil
463
+
464
+ @task.Definition.Actions.each do |action|
465
+ param = action.Arguments if action.Type == 0
466
+ end
467
+
468
+ param
469
+ end
470
+
471
+ # Sets the parameters for the task. These parameters are passed as command
472
+ # line arguments to the application the task will run. To clear the command
473
+ # line parameters set it to an empty string.
474
+ #--
475
+ # NOTE: Again, it seems the task must be reactivated to be picked up.
476
+ #
477
+ def parameters=(param)
478
+ raise TypeError unless param.is_a?(String)
479
+ check_for_active_task
480
+
481
+ definition = @task.Definition
482
+
483
+ definition.Actions.each do |action|
484
+ action.Arguments = param if action.Type == 0
485
+ end
486
+
487
+ update_task_definition(definition)
488
+
489
+ param
490
+ end
491
+
492
+ # Returns the working directory for the task.
493
+ #
494
+ def working_directory
495
+ check_for_active_task
496
+
497
+ dir = nil
498
+
499
+ @task.Definition.Actions.each do |action|
500
+ dir = action.WorkingDirectory if action.Type == 0
501
+ end
502
+
503
+ dir
504
+ end
505
+
506
+ # Sets the working directory for the task.
507
+ #--
508
+ # TODO: Why do I have to reactivate the task to see the change?
509
+ #
510
+ def working_directory=(dir)
511
+ raise TypeError unless dir.is_a?(String)
512
+ check_for_active_task
513
+
514
+ definition = @task.Definition
515
+
516
+ definition.Actions.each do |action|
517
+ action.WorkingDirectory = dir if action.Type == 0
518
+ end
519
+
520
+ update_task_definition(definition)
521
+
522
+ dir
523
+ end
524
+
525
+ # Returns the task's priority level. Possible values are 'idle',
526
+ # 'normal', 'high', 'realtime', 'below_normal', 'above_normal',
527
+ # and 'unknown'.
528
+ #
529
+ def priority
530
+ check_for_active_task
531
+
532
+ case @task.Definition.Settings.Priority
533
+ when 0
534
+ priority = 'critical'
535
+ when 1
536
+ priority = 'highest'
537
+ when 2
538
+ priority = 'above_normal'
539
+ when 3
540
+ priority = 'above_normal'
541
+ when 4
542
+ priority = 'normal'
543
+ when 5
544
+ priority = 'normal'
545
+ when 6
546
+ priority = 'normal'
547
+ when 7
548
+ priority = 'below_normal'
549
+ when 8
550
+ priority = 'below_normal'
551
+ when 9
552
+ priority = 'lowest'
553
+ when 10
554
+ priority = 'idle'
555
+ else
556
+ priority = 'unknown'
557
+ end
558
+
559
+ priority
560
+ end
561
+
562
+ # Sets the priority of the task. The +priority+ should be a numeric
563
+ # priority constant value.
564
+ #
565
+ def priority=(priority)
566
+ raise TypeError unless priority.is_a?(Numeric)
567
+ check_for_active_task
568
+
569
+ definition = @task.Definition
570
+ definition.Settings.Priority = priority
571
+
572
+ update_task_definition(definition)
573
+
574
+ priority
575
+ end
576
+
577
+ # Creates a new work item (scheduled job) with the given +trigger+. The
578
+ # trigger variable is a hash of options that define when the scheduled
579
+ # job should run.
580
+ #
581
+ def new_work_item(task, trigger)
582
+ raise TypeError unless task.is_a?(String)
583
+ raise TypeError unless trigger.is_a?(Hash)
584
+
585
+ validate_trigger(trigger)
586
+
587
+ taskDefinition = @service.NewTask(0)
588
+ taskDefinition.RegistrationInfo.Description = ''
589
+ taskDefinition.RegistrationInfo.Author = ''
590
+ taskDefinition.Settings.StartWhenAvailable = true
591
+ taskDefinition.Settings.Enabled = true
592
+ taskDefinition.Settings.Hidden = false
593
+
594
+ case trigger[:trigger_type]
595
+ when TASK_TIME_TRIGGER_ONCE
596
+ type = 1
597
+ when TASK_TIME_TRIGGER_DAILY
598
+ type = 2
599
+ when TASK_TIME_TRIGGER_WEEKLY
600
+ type = 3
601
+ when TASK_TIME_TRIGGER_MONTHLYDATE
602
+ type = 4
603
+ when TASK_TIME_TRIGGER_MONTHLYDOW
604
+ type = 5
605
+ when TASK_EVENT_TRIGGER_ON_IDLE
606
+ type = 6
607
+ when TASK_EVENT_TRIGGER_AT_SYSTEMSTART
608
+ type = 8
609
+ when TASK_EVENT_TRIGGER_AT_LOGON
610
+ type = 9
611
+ else
612
+ raise ArgumentError, 'Unknown trigger type'
613
+ end
614
+
615
+ startTime = "%04d-%02d-%02dT%02d:%02d:00" % [
616
+ trigger[:start_year], trigger[:start_month], trigger[:start_day],
617
+ trigger[:start_hour], trigger[:start_minute]
618
+ ]
619
+
620
+ # Set defaults
621
+ trigger[:end_year] ||= 0
622
+ trigger[:end_month] ||= 0
623
+ trigger[:end_day] ||= 0
624
+
625
+ endTime = "%04d-%02d-%02dT00:00:00" % [
626
+ trigger[:end_year], trigger[:end_month], trigger[:end_day]
627
+ ]
628
+
629
+ trig = taskDefinition.Triggers.Create(type)
630
+ trig.Id = "RegistrationTriggerId#{taskDefinition.Triggers.Count}"
631
+ trig.StartBoundary = startTime
632
+ trig.EndBoundary = endTime if endTime != '0000-00-00T00:00:00'
633
+ trig.Enabled = true
634
+
635
+ repetitionPattern = trig.Repetition
636
+
637
+ if trigger[:minutes_duration].to_i > 0
638
+ repetitionPattern.Duration = "PT#{trigger[:minutes_duration]||0}M"
639
+ end
640
+
641
+ if trigger[:minutes_interval].to_i > 0
642
+ repetitionPattern.Interval = "PT#{trigger[:minutes_interval]||0}M"
643
+ end
644
+
645
+ tmp = trigger[:type]
646
+ tmp = nil unless tmp.is_a?(Hash)
647
+
648
+ case trigger[:trigger_type]
649
+ when TASK_TIME_TRIGGER_DAILY
650
+ trig.DaysInterval = tmp[:days_interval] if tmp && tmp[:days_interval]
651
+ if trigger[:random_minutes_interval].to_i > 0
652
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]}M"
653
+ end
654
+ when TASK_TIME_TRIGGER_WEEKLY
655
+ trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
656
+ trig.WeeksInterval = tmp[:weeks_interval] if tmp && tmp[:weeks_interval]
657
+ if trigger[:random_minutes_interval].to_i > 0
658
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
659
+ end
660
+ when TASK_TIME_TRIGGER_MONTHLYDATE
661
+ trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
662
+ trig.DaysOfMonth = tmp[:days] if tmp && tmp[:days]
663
+ if trigger[:random_minutes_interval].to_i > 0
664
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
665
+ end
666
+ when TASK_TIME_TRIGGER_MONTHLYDOW
667
+ trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
668
+ trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
669
+ trig.WeeksOfMonth = tmp[:weeks] if tmp && tmp[:weeks]
670
+ if trigger[:random_minutes_interval].to_i>0
671
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
672
+ end
673
+ when TASK_TIME_TRIGGER_ONCE
674
+ if trigger[:random_minutes_interval].to_i > 0
675
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
676
+ end
677
+ end
678
+
679
+ act = taskDefinition.Actions.Create(0)
680
+ act.Path = 'cmd'
681
+
682
+
683
+ begin
684
+ @task = @root.RegisterTaskDefinition(
685
+ task,
686
+ taskDefinition,
687
+ TASK_CREATE_OR_UPDATE,
688
+ nil,
689
+ nil,
690
+ TASK_LOGON_INTERACTIVE_TOKEN
691
+ )
692
+ rescue WIN32OLERuntimeError => err
693
+ raise Error, ole_error('RegisterTaskDefinition', err)
694
+ end
695
+
696
+ @task = @root.GetTask(task)
697
+ end
698
+
699
+ alias new_task new_work_item
700
+
701
+ # Returns the number of triggers associated with the active task.
702
+ #
703
+ def trigger_count
704
+ raise Error, "No currently active task" if @task.nil?
705
+
706
+ @task.Definition.Triggers.Count
707
+ end
708
+
709
+ # Returns a string that describes the current trigger at the specified
710
+ # index for the active task.
711
+ #
712
+ # Example: "At 7:14 AM every day, starting 4/11/2015"
713
+ #
714
+ def trigger_string(index)
715
+ raise TypeError unless index.is_a?(Numeric)
716
+ check_for_active_task
717
+ index += 1 # first item index is 1
718
+
719
+ begin
720
+ trigger = @task.Definition.Triggers.Item(index)
721
+ rescue WIN32OLERuntimeError
722
+ raise Error, "No trigger found at index '#{index}'"
723
+ end
724
+
725
+ "Starting #{trigger.StartBoundary}"
726
+ end
727
+
728
+ # Deletes the trigger at the specified index.
729
+ #--
730
+ # TODO: Fix.
731
+ #
732
+ def delete_trigger(index)
733
+ raise TypeError unless index.is_a?(Numeric)
734
+ check_for_active_task
735
+ index += 1 # first item index is 1
736
+
737
+ definition = @task.Definition
738
+ definition.Triggers.Remove(index)
739
+ update_task_definition(definition)
740
+
741
+ index
742
+ end
743
+
744
+ # Returns a hash that describes the trigger at the given index for the
745
+ # current task.
746
+ #
747
+ def trigger(index)
748
+ raise TypeError unless index.is_a?(Numeric)
749
+ check_for_active_task
750
+ index += 1 # first item index is 1
751
+
752
+ begin
753
+ trig = @task.Definition.Triggers.Item(index)
754
+ rescue WIN32OLERuntimeError => err
755
+ raise Error, ole_error('Item', err)
756
+ end
757
+
758
+ trigger = {}
759
+ trigger[:start_year], trigger[:start_month],
760
+ trigger[:start_day], trigger[:start_hour],
761
+ trigger[:start_minute] = trig.StartBoundary.scan(/(\d+)-(\d+)-(\d+)T(\d+):(\d+)/).first
762
+
763
+ trigger[:end_year], trigger[:end_month],
764
+ trigger[:end_day] = trig.StartBoundary.scan(/(\d+)-(\d+)-(\d+)T/).first
765
+
766
+ if trig.Repetition.Duration != ""
767
+ trigger[:minutes_duration] = trig.Repetition.Duration.scan(/(\d+)M/)[0][0].to_i
768
+ end
769
+
770
+ if trig.Repetition.Interval != ""
771
+ trigger[:minutes_interval] = trig.Repetition.Interval.scan(/(\d+)M/)[0][0].to_i
772
+ end
773
+
774
+ if trig.RandomDelay != ""
775
+ trigger[:random_minutes_interval] = trig.RandomDelay.scan(/(\d+)M/)[0][0].to_i
776
+ end
777
+
778
+ case trig.Type
779
+ when 2
780
+ trigger[:trigger_type] = TASK_TIME_TRIGGER_DAILY
781
+ tmp = {}
782
+ tmp[:days_interval] = trig.DaysInterval
783
+ trigger[:type] = tmp
784
+ when 3
785
+ trigger[:trigger_type] = TASK_TIME_TRIGGER_WEEKLY
786
+ tmp = {}
787
+ tmp[:weeks_interval] = trig.WeeksInterval
788
+ tmp[:days_of_week] = trig.DaysOfWeek
789
+ trigger[:type] = tmp
790
+ when 4
791
+ trigger[:trigger_type] = TASK_TIME_TRIGGER_MONTHLYDATE
792
+ tmp = {}
793
+ tmp[:months] = trig.MonthsOfYear
794
+ tmp[:days] = trig.DaysOfMonth
795
+ trigger[:type] = tmp
796
+ when 5
797
+ trigger[:trigger_type] = TASK_TIME_TRIGGER_MONTHLYDOW
798
+ tmp = {}
799
+ tmp[:months] = trig.MonthsOfYear
800
+ tmp[:days_of_week] = trig.DaysOfWeek
801
+ tmp[:weeks] = trig.weeks
802
+ trigger[:type] = tmp
803
+ when 1
804
+ trigger[:trigger_type] = TASK_TIME_TRIGGER_ONCE
805
+ tmp = {}
806
+ tmp[:once] = nil
807
+ trigger[:type] = tmp
808
+ else
809
+ raise Error, 'Unknown trigger type'
810
+ end
811
+
812
+ trigger
813
+ end
814
+
815
+ # Sets the trigger for the currently active task. The +trigger+ is a hash
816
+ # with the following possible options:
817
+ #
818
+ # * days
819
+ # * days_interval
820
+ # * days_of_week
821
+ # * end_day
822
+ # * end_month
823
+ # * end_year
824
+ # * flags
825
+ # * minutes_duration
826
+ # * minutes_interval
827
+ # * months
828
+ # * random_minutes_interval
829
+ # * start_day
830
+ # * start_hour
831
+ # * start_minute
832
+ # * start_month
833
+ # * start_year
834
+ # * trigger_type
835
+ # * type
836
+ # * weeks
837
+ # * weeks_interval
838
+ #
839
+ def trigger=(trigger)
840
+ raise TypeError unless trigger.is_a?(Hash)
841
+ check_for_active_task
842
+
843
+ validate_trigger(trigger)
844
+
845
+ definition = @task.Definition
846
+ definition.Triggers.Clear()
847
+
848
+ case trigger[:trigger_type]
849
+ when TASK_TIME_TRIGGER_ONCE
850
+ type = 1
851
+ when TASK_TIME_TRIGGER_DAILY
852
+ type = 2
853
+ when TASK_TIME_TRIGGER_WEEKLY
854
+ type = 3
855
+ when TASK_TIME_TRIGGER_MONTHLYDATE
856
+ type = 4
857
+ when TASK_TIME_TRIGGER_MONTHLYDOW
858
+ type = 5
859
+ when TASK_EVENT_TRIGGER_ON_IDLE
860
+ type = 6
861
+ when TASK_EVENT_TRIGGER_AT_SYSTEM_START
862
+ type = 8
863
+ when TASK_EVENT_TRIGGER_AT_LOGON
864
+ type = 9
865
+ else
866
+ raise Error, 'Unknown trigger type'
867
+ end
868
+
869
+ startTime = "%04d-%02d-%02dT%02d:%02d:00" % [
870
+ trigger[:start_year], trigger[:start_month],
871
+ trigger[:start_day], trigger[:start_hour], trigger[:start_minute]
872
+ ]
873
+
874
+ endTime = "%04d-%02d-%02dT00:00:00" % [
875
+ trigger[:end_year], trigger[:end_month], trigger[:end_day]
876
+ ]
877
+
878
+ trig = definition.Triggers.Create(type)
879
+ trig.Id = "RegistrationTriggerId#{definition.Triggers.Count}"
880
+ trig.StartBoundary = startTime
881
+ trig.EndBoundary = endTime if endTime != '0000-00-00T00:00:00'
882
+ trig.Enabled = true
883
+
884
+ repetitionPattern = trig.Repetition
885
+
886
+ if trigger[:minutes_duration].to_i > 0
887
+ repetitionPattern.Duration = "PT#{trigger[:minutes_duration]||0}M"
888
+ end
889
+
890
+ if trigger[:minutes_interval].to_i > 0
891
+ repetitionPattern.Interval = "PT#{trigger[:minutes_interval]||0}M"
892
+ end
893
+
894
+ tmp = trigger[:type]
895
+ tmp = nil unless tmp.is_a?(Hash)
896
+
897
+ case trigger[:trigger_type]
898
+ when TASK_TIME_TRIGGER_DAILY
899
+ trig.DaysInterval = tmp[:days_interval] if tmp && tmp[:days_interval]
900
+ if trigger[:random_minutes_interval].to_i > 0
901
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]}M"
902
+ end
903
+ when TASK_TIME_TRIGGER_WEEKLY
904
+ trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
905
+ trig.WeeksInterval = tmp[:weeks_interval] if tmp && tmp[:weeks_interval]
906
+ if trigger[:random_minutes_interval].to_i > 0
907
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
908
+ end
909
+ when TASK_TIME_TRIGGER_MONTHLYDATE
910
+ trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
911
+ trig.DaysOfMonth = tmp[:days] if tmp && tmp[:days]
912
+ if trigger[:random_minutes_interval].to_i > 0
913
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
914
+ end
915
+ when TASK_TIME_TRIGGER_MONTHLYDOW
916
+ trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
917
+ trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
918
+ trig.WeeksOfMonth = tmp[:weeks] if tmp && tmp[:weeks]
919
+ if trigger[:random_minutes_interval].to_i > 0
920
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
921
+ end
922
+ when TASK_TIME_TRIGGER_ONCE
923
+ if trigger[:random_minutes_interval].to_i > 0
924
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
925
+ end
926
+ end
927
+
928
+ update_task_definition(definition)
929
+
930
+ trigger
931
+ end
932
+
933
+ # Adds a trigger at the specified index.
934
+ #
935
+ def add_trigger(index, trigger)
936
+ raise TypeError unless index.is_a?(Numeric)
937
+ raise TypeError unless trigger.is_a?(Hash)
938
+ check_for_active_task
939
+
940
+ definition = @task.Definition
941
+ case trigger[:trigger_type]
942
+ when TASK_TIME_TRIGGER_DAILY
943
+ type = 2
944
+ when TASK_TIME_TRIGGER_WEEKLY
945
+ type = 3
946
+ when TASK_TIME_TRIGGER_MONTHLYDATE
947
+ type = 4
948
+ when TASK_TIME_TRIGGER_MONTHLYDOW
949
+ type = 5
950
+ when TASK_TIME_TRIGGER_ONCE
951
+ type = 1
952
+ else
953
+ raise Error, 'Unknown trigger type'
954
+ end
955
+
956
+ startTime = "%04d-%02d-%02dT%02d:%02d:00" % [
957
+ trigger[:start_year], trigger[:start_month], trigger[:start_day],
958
+ trigger[:start_hour], trigger[:start_minute]
959
+ ]
960
+
961
+ # Set defaults
962
+ trigger[:end_year] ||= 0
963
+ trigger[:end_month] ||= 0
964
+ trigger[:end_day] ||= 0
965
+
966
+ endTime = "%04d-%02d-%02dT00:00:00" % [
967
+ trigger[:end_year], trigger[:end_month], trigger[:end_day]
968
+ ]
969
+
970
+ trig = definition.Triggers.Create(type)
971
+ trig.Id = "RegistrationTriggerId#{definition.Triggers.Count}"
972
+ trig.StartBoundary = startTime
973
+ trig.EndBoundary = endTime if endTime != '0000-00-00T00:00:00'
974
+ trig.Enabled = true
975
+
976
+ repetitionPattern = trig.Repetition
977
+
978
+ if trigger[:minutes_duration].to_i > 0
979
+ repetitionPattern.Duration = "PT#{trigger[:minutes_duration]||0}M"
980
+ end
981
+
982
+ if trigger[:minutes_interval].to_i > 0
983
+ repetitionPattern.Interval = "PT#{trigger[:minutes_interval]||0}M"
984
+ end
985
+
986
+ tmp = trigger[:type]
987
+ tmp = nil unless tmp.is_a?(Hash)
988
+
989
+ case trigger[:trigger_type]
990
+ when TASK_TIME_TRIGGER_DAILY
991
+ trig.DaysInterval = tmp[:days_interval] if tmp && tmp[:days_interval]
992
+ if trigger[:random_minutes_interval].to_i > 0
993
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]}M"
994
+ end
995
+ when TASK_TIME_TRIGGER_WEEKLY
996
+ trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
997
+ trig.WeeksInterval = tmp[:weeks_interval] if tmp && tmp[:weeks_interval]
998
+ if trigger[:random_minutes_interval].to_i > 0
999
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
1000
+ end
1001
+ when TASK_TIME_TRIGGER_MONTHLYDATE
1002
+ trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
1003
+ trig.DaysOfMonth = tmp[:days] if tmp && tmp[:days]
1004
+ if trigger[:random_minutes_interval].to_i > 0
1005
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
1006
+ end
1007
+ when TASK_TIME_TRIGGER_MONTHLYDOW
1008
+ trig.MonthsOfYear = tmp[:months] if tmp && tmp[:months]
1009
+ trig.DaysOfWeek = tmp[:days_of_week] if tmp && tmp[:days_of_week]
1010
+ trig.WeeksOfMonth = tmp[:weeks] if tmp && tmp[:weeks]
1011
+ if trigger[:random_minutes_interval].to_i > 0
1012
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
1013
+ end
1014
+ when TASK_TIME_TRIGGER_ONCE
1015
+ if trigger[:random_minutes_interval].to_i > 0
1016
+ trig.RandomDelay = "PT#{trigger[:random_minutes_interval]||0}M"
1017
+ end
1018
+ end
1019
+
1020
+ update_task_definition(definition)
1021
+
1022
+ true
1023
+ end
1024
+
1025
+ # Returns the status of the currently active task. Possible values are
1026
+ # 'ready', 'running', 'not scheduled' or 'unknown'.
1027
+ #
1028
+ def status
1029
+ check_for_active_task
1030
+
1031
+ case @task.State
1032
+ when 3
1033
+ status = 'ready'
1034
+ when 4
1035
+ status = 'running'
1036
+ when 1
1037
+ status = 'not scheduled'
1038
+ else
1039
+ status = 'unknown'
1040
+ end
1041
+
1042
+ status
1043
+ end
1044
+
1045
+ # Returns the exit code from the last scheduled run.
1046
+ #
1047
+ def exit_code
1048
+ check_for_active_task
1049
+ @task.LastTaskResult
1050
+ end
1051
+
1052
+ # Returns the comment associated with the task, if any.
1053
+ #
1054
+ def comment
1055
+ check_for_active_task
1056
+ @task.Definition.RegistrationInfo.Description
1057
+ end
1058
+
1059
+ alias description comment
1060
+
1061
+ # Sets the comment for the task.
1062
+ #
1063
+ def comment=(comment)
1064
+ raise TypeError unless comment.is_a?(String)
1065
+ check_for_active_task
1066
+
1067
+ definition = @task.Definition
1068
+ definition.RegistrationInfo.Description = comment
1069
+ update_task_definition(definition)
1070
+
1071
+ comment
1072
+ end
1073
+
1074
+ alias description= comment=
1075
+
1076
+ # Returns the name of the user who created the task.
1077
+ #
1078
+ def creator
1079
+ check_for_active_task
1080
+ @task.Definition.RegistrationInfo.Author
1081
+ end
1082
+
1083
+ alias author creator
1084
+
1085
+ # Sets the creator for the task.
1086
+ #
1087
+ def creator=(creator)
1088
+ raise TypeError unless creator.is_a?(String)
1089
+ check_for_active_task
1090
+
1091
+ definition = @task.Definition
1092
+ definition.RegistrationInfo.Author = creator
1093
+ update_task_definition(definition)
1094
+
1095
+ creator
1096
+ end
1097
+
1098
+ alias author= creator=
1099
+
1100
+ # Returns a Time object that indicates the next time the task will run.
1101
+ #
1102
+ def next_run_time
1103
+ check_for_active_task
1104
+ @task.NextRunTime
1105
+ end
1106
+
1107
+ # Returns a Time object indicating the most recent time the task ran or
1108
+ # nil if the task has never run.
1109
+ #
1110
+ def most_recent_run_time
1111
+ check_for_active_task
1112
+
1113
+ time = nil
1114
+
1115
+ begin
1116
+ time = Time.parse(@task.LastRunTime)
1117
+ rescue
1118
+ # Ignore
1119
+ end
1120
+
1121
+ time
1122
+ end
1123
+
1124
+ # Returns the maximum length of time, in milliseconds, that the task
1125
+ # will run before terminating.
1126
+ #
1127
+ def max_run_time
1128
+ check_for_active_task
1129
+
1130
+ t = @task.Definition.Settings.ExecutionTimeLimit
1131
+ year = t.scan(/(\d+?)Y/).flatten.first
1132
+ month = t.scan(/(\d+?)M/).flatten.first
1133
+ day = t.scan(/(\d+?)D/).flatten.first
1134
+ hour = t.scan(/(\d+?)H/).flatten.first
1135
+ min = t.scan(/T.*(\d+?)M/).flatten.first
1136
+ sec = t.scan(/(\d+?)S/).flatten.first
1137
+
1138
+ time = 0
1139
+ time += year.to_i * 365 if year
1140
+ time += month.to_i * 30 if month
1141
+ time += day.to_i if day
1142
+ time *= 24
1143
+ time += hour.to_i if hour
1144
+ time *= 60
1145
+ time += min.to_i if min
1146
+ time *= 60
1147
+ time += sec.to_i if sec
1148
+ time *= 1000
1149
+
1150
+ time
1151
+ end
1152
+
1153
+ # Sets the maximum length of time, in milliseconds, that the task can run
1154
+ # before terminating. Returns the value you specified if successful.
1155
+ #
1156
+ def max_run_time=(max_run_time)
1157
+ raise TypeError unless max_run_time.is_a?(Numeric)
1158
+ check_for_active_task
1159
+
1160
+ t = max_run_time
1161
+ t /= 1000
1162
+ limit ="PT#{t}S"
1163
+
1164
+ definition = @task.Definition
1165
+ definition.Settings.ExecutionTimeLimit = limit
1166
+ update_task_definition(definition)
1167
+
1168
+ max_run_time
1169
+ end
1170
+
1171
+ # Accepts a hash that lets you configure various task definition settings.
1172
+ # The possible options are:
1173
+ #
1174
+ # * allow_demand_start
1175
+ # * allow_hard_terminate
1176
+ # * compatibility
1177
+ # * delete_expired_task_after
1178
+ # * disallowed_start_if_on_batteries
1179
+ # * enabled
1180
+ # * execution_time_limit (or max_run_time)
1181
+ # * hidden
1182
+ # * idle_settings
1183
+ # * network_settings
1184
+ # * priority
1185
+ # * restart_count
1186
+ # * restart_interval
1187
+ # * run_only_if_idle
1188
+ # * run_only_if_network_available
1189
+ # * start_when_available
1190
+ # * stop_if_going_on_batteries
1191
+ # * wake_to_run
1192
+ # * xml_text (or xml)
1193
+ #
1194
+ def configure_settings(hash)
1195
+ raise TypeError unless hash.is_a?(Hash)
1196
+ check_for_active_task
1197
+
1198
+ definition = @task.Definition
1199
+
1200
+ allow_demand_start = hash[:allow_demand_start]
1201
+ allow_hard_terminate = hash[:allow_hard_terminate]
1202
+ compatibility = hash[:compatibility]
1203
+ delete_expired_task_after = hash[:delete_expired_task_after]
1204
+ disallow_start_if_on_batteries = hash[:disallow_start_if_on_batteries]
1205
+ enabled = hash[:enabled]
1206
+ execution_time_limit = hash[:execution_time_limit] || hash[:max_run_time]
1207
+ hidden = hash[:hidden]
1208
+ idle_settings = hash[:idle_settings]
1209
+ network_settings = hash[:network_settings]
1210
+ priority = hash[:priority]
1211
+ restart_count = hash[:restart_count]
1212
+ restart_interval = hash[:restart_interval]
1213
+ run_only_if_idle = hash[:run_only_if_idle]
1214
+ run_only_if_network_available = hash[:run_only_if_network_available]
1215
+ start_when_available = hash[:start_when_available]
1216
+ stop_if_going_on_batteries = hash[:stop_if_going_on_batteries]
1217
+ wake_to_run = hash[:wake_to_run]
1218
+ xml_text = hash[:xml_text] || hash[:xml]
1219
+
1220
+ definition.Settings.AllowDemandStart = allow_demand_start if allow_demand_start
1221
+ definition.Settings.AllowHardTerminate = allow_hard_terminate if allow_hard_terminate
1222
+ definition.Settings.Compatibility = compatibility if compatibility
1223
+ definition.Settings.DeleteExpiredTaskAfter = delete_expired_task_after if delete_expired_task_after
1224
+ definition.Settings.DisallowStartIfOnBatteries = disallow_start_if_on_batteries if disallow_start_if_on_batteries
1225
+ definition.Settings.Enabled = enabled if enabled
1226
+ definition.Settings.ExecutionTimeLimit = execution_time_limit if execution_time_limit
1227
+ definition.Settings.Hidden = hidden if hidden
1228
+ definition.Settings.IdleSettings = idle_settings if idle_settings
1229
+ definition.Settings.NetworkSettings = network_settings if network_settings
1230
+ definition.Settings.Priority = priority if priority
1231
+ definition.Settings.RestartCount = restart_count if restart_count
1232
+ definition.Settings.RestartInterval = restart_interval if restart_interval
1233
+ definition.Settings.RunOnlyIfIdle = run_only_if_idle if run_only_if_idle
1234
+ definition.Settings.RunOnlyIfNetworkAvailable = run_only_if_network_available if run_only_if_network_available
1235
+ definition.Settings.StartWhenAvailable = start_when_available if start_when_available
1236
+ definition.Settings.StopIfGoingOnBatteries = stop_if_going_on_batteries if stop_if_going_on_batteries
1237
+ definition.Settings.WakeToRun = wake_to_run if wake_to_run
1238
+ definition.Settings.XmlText = xml_text if xml_text
1239
+
1240
+ update_task_definition(definition)
1241
+
1242
+ hash
1243
+ end
1244
+
1245
+ # Set registration information options. The possible options are:
1246
+ #
1247
+ # * author
1248
+ # * date
1249
+ # * description (or comment)
1250
+ # * documentation
1251
+ # * security_descriptor (should be a Win32::Security::SID)
1252
+ # * source
1253
+ # * uri
1254
+ # * version
1255
+ # * xml_text (or xml)
1256
+ #
1257
+ # Note that most of these options have standalone methods as well,
1258
+ # e.g. calling ts.configure_registration_info(:author => 'Dan') is
1259
+ # the same as calling ts.author = 'Dan'.
1260
+ #
1261
+ def configure_registration_info(hash)
1262
+ raise TypeError unless hash.is_a?(Hash)
1263
+ check_for_active_task
1264
+
1265
+ definition = @task.Definition
1266
+
1267
+ author = hash[:author]
1268
+ date = hash[:date]
1269
+ description = hash[:description] || hash[:comment]
1270
+ documentation = hash[:documentation]
1271
+ security_descriptor = hash[:security_descriptor]
1272
+ source = hash[:source]
1273
+ uri = hash[:uri]
1274
+ version = hash[:version]
1275
+ xml_text = hash[:xml_text] || hash[:xml]
1276
+
1277
+ definition.RegistrationInfo.Author = author if author
1278
+ definition.RegistrationInfo.Date = date if date
1279
+ definition.RegistrationInfo.Description = description if description
1280
+ definition.RegistrationInfo.Documentation = documentation if documentation
1281
+ definition.RegistrationInfo.SecurityDescriptor = security_descriptor if security_descriptor
1282
+ definition.RegistrationInfo.Source = source if source
1283
+ definition.RegistrationInfo.URI = uri if uri
1284
+ definition.RegistrationInfo.Version = version if version
1285
+ definition.RegistrationInfo.XmlText = xml_text if xml_text
1286
+
1287
+ update_task_definition(definition)
1288
+
1289
+ hash
1290
+ end
1291
+
1292
+ # Shorthand constants
1293
+
1294
+ IDLE = IDLE_PRIORITY_CLASS
1295
+ NORMAL = NORMAL_PRIORITY_CLASS
1296
+ HIGH = HIGH_PRIORITY_CLASS
1297
+ REALTIME = REALTIME_PRIORITY_CLASS
1298
+ BELOW_NORMAL = BELOW_NORMAL_PRIORITY_CLASS
1299
+ ABOVE_NORMAL = ABOVE_NORMAL_PRIORITY_CLASS
1300
+
1301
+ ONCE = TASK_TIME_TRIGGER_ONCE
1302
+ DAILY = TASK_TIME_TRIGGER_DAILY
1303
+ WEEKLY = TASK_TIME_TRIGGER_WEEKLY
1304
+ MONTHLYDATE = TASK_TIME_TRIGGER_MONTHLYDATE
1305
+ MONTHLYDOW = TASK_TIME_TRIGGER_MONTHLYDOW
1306
+
1307
+ ON_IDLE = TASK_EVENT_TRIGGER_ON_IDLE
1308
+ AT_SYSTEMSTART = TASK_EVENT_TRIGGER_AT_SYSTEMSTART
1309
+ AT_LOGON = TASK_EVENT_TRIGGER_AT_LOGON
1310
+ FIRST_WEEK = TASK_FIRST_WEEK
1311
+ SECOND_WEEK = TASK_SECOND_WEEK
1312
+ THIRD_WEEK = TASK_THIRD_WEEK
1313
+ FOURTH_WEEK = TASK_FOURTH_WEEK
1314
+ LAST_WEEK = TASK_LAST_WEEK
1315
+ SUNDAY = TASK_SUNDAY
1316
+ MONDAY = TASK_MONDAY
1317
+ TUESDAY = TASK_TUESDAY
1318
+ WEDNESDAY = TASK_WEDNESDAY
1319
+ THURSDAY = TASK_THURSDAY
1320
+ FRIDAY = TASK_FRIDAY
1321
+ SATURDAY = TASK_SATURDAY
1322
+ JANUARY = TASK_JANUARY
1323
+ FEBRUARY = TASK_FEBRUARY
1324
+ MARCH = TASK_MARCH
1325
+ APRIL = TASK_APRIL
1326
+ MAY = TASK_MAY
1327
+ JUNE = TASK_JUNE
1328
+ JULY = TASK_JULY
1329
+ AUGUST = TASK_AUGUST
1330
+ SEPTEMBER = TASK_SEPTEMBER
1331
+ OCTOBER = TASK_OCTOBER
1332
+ NOVEMBER = TASK_NOVEMBER
1333
+ DECEMBER = TASK_DECEMBER
1334
+
1335
+ INTERACTIVE = TASK_FLAG_INTERACTIVE
1336
+ DELETE_WHEN_DONE = TASK_FLAG_DELETE_WHEN_DONE
1337
+ DISABLED = TASK_FLAG_DISABLED
1338
+ START_ONLY_IF_IDLE = TASK_FLAG_START_ONLY_IF_IDLE
1339
+ KILL_ON_IDLE_END = TASK_FLAG_KILL_ON_IDLE_END
1340
+ DONT_START_IF_ON_BATTERIES = TASK_FLAG_DONT_START_IF_ON_BATTERIES
1341
+ KILL_IF_GOING_ON_BATTERIES = TASK_FLAG_KILL_IF_GOING_ON_BATTERIES
1342
+ RUN_ONLY_IF_DOCKED = TASK_FLAG_RUN_ONLY_IF_DOCKED
1343
+ HIDDEN = TASK_FLAG_HIDDEN
1344
+ RUN_IF_CONNECTED_TO_INTERNET = TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET
1345
+ RESTART_ON_IDLE_RESUME = TASK_FLAG_RESTART_ON_IDLE_RESUME
1346
+ SYSTEM_REQUIRED = TASK_FLAG_SYSTEM_REQUIRED
1347
+ RUN_ONLY_IF_LOGGED_ON = TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
1348
+
1349
+ FLAG_HAS_END_DATE = TASK_TRIGGER_FLAG_HAS_END_DATE
1350
+ FLAG_KILL_AT_DURATION_END = TASK_TRIGGER_FLAG_KILL_AT_DURATION_END
1351
+ FLAG_DISABLED = TASK_TRIGGER_FLAG_DISABLED
1352
+
1353
+ MAX_RUN_TIMES = TASK_MAX_RUN_TIMES
1354
+
1355
+ private
1356
+
1357
+ def validate_trigger(hash)
1358
+ [:start_year, :start_month, :start_day].each{ |key|
1359
+ raise ArgumentError, "#{key} must be set" unless hash[key]
1360
+ }
1361
+ end
1362
+
1363
+ def check_for_active_task
1364
+ raise Error, 'No currently active task' if @task.nil?
1365
+ end
1366
+
1367
+ def update_task_definition(definition)
1368
+ user = definition.Principal.UserId
1369
+
1370
+ @task = @root.RegisterTaskDefinition(
1371
+ @task.Path,
1372
+ definition,
1373
+ TASK_CREATE_OR_UPDATE,
1374
+ user,
1375
+ @password,
1376
+ @password ? TASK_LOGON_PASSWORD : TASK_LOGON_INTERACTIVE_TOKEN
1377
+ )
1378
+ rescue WIN32OLERuntimeError => err
1379
+ method_name = caller_locations(1,1)[0].label
1380
+ raise Error, ole_error(method_name, err)
1381
+ end
1382
+ end
1383
+ end