bolt 0.21.7 → 0.21.8
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bolt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/bolt/transport/ssh/connection.rb +4 -5
- data/lib/bolt/transport/ssh.rb +4 -1
- data/lib/bolt/transport/winrm/connection.rb +3 -4
- data/lib/bolt/transport/winrm.rb +4 -1
- data/lib/bolt/version.rb +1 -1
- data/libexec/apply_catalog.rb +10 -2
- data/vendored/puppet/lib/puppet/application/apply.rb +20 -9
- data/vendored/puppet/lib/puppet/application/cert.rb +3 -1
- data/vendored/puppet/lib/puppet/application/device.rb +22 -5
- data/vendored/puppet/lib/puppet/configurer/fact_handler.rb +5 -1
- data/vendored/puppet/lib/puppet/configurer.rb +15 -2
- data/vendored/puppet/lib/puppet/defaults.rb +36 -25
- data/vendored/puppet/lib/puppet/face/certificate.rb +2 -0
- data/vendored/puppet/lib/puppet/feature/base.rb +0 -3
- data/vendored/puppet/lib/puppet/functions/call.rb +37 -0
- data/vendored/puppet/lib/puppet/functions.rb +5 -0
- data/vendored/puppet/lib/puppet/indirector/ldap.rb +6 -0
- data/vendored/puppet/lib/puppet/node/environment.rb +4 -2
- data/vendored/puppet/lib/puppet/parser/scope.rb +2 -2
- data/vendored/puppet/lib/puppet/pops/adapters.rb +14 -0
- data/vendored/puppet/lib/puppet/pops/evaluator/deferred_resolver.rb +128 -0
- data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +4 -1
- data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +2 -0
- data/vendored/puppet/lib/puppet/pops/issues.rb +9 -1
- data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -16
- data/vendored/puppet/lib/puppet/pops/loaders.rb +1 -3
- data/vendored/puppet/lib/puppet/pops/parser/eparser.rb +6 -6
- data/vendored/puppet/lib/puppet/pops/pcore.rb +11 -0
- data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +17 -0
- data/vendored/puppet/lib/puppet/pops/validation/tasks_checker.rb +13 -5
- data/vendored/puppet/lib/puppet/pops.rb +1 -0
- data/vendored/puppet/lib/puppet/provider/service/debian.rb +1 -0
- data/vendored/puppet/lib/puppet/provider/service/smf.rb +2 -3
- data/vendored/puppet/lib/puppet/provider/service/upstart.rb +10 -2
- data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +6 -84
- data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +11 -3
- data/vendored/puppet/lib/puppet/type/file.rb +3 -0
- data/vendored/puppet/lib/puppet/type/user.rb +17 -3
- data/vendored/puppet/lib/puppet/util/autoload.rb +36 -31
- data/vendored/puppet/lib/puppet/util.rb +2 -0
- metadata +3 -43
- data/vendored/puppet/lib/puppet/indirector/node/write_only_yaml.rb +0 -39
- data/vendored/puppet/lib/puppet/provider/augeas/augeas.rb +0 -573
- data/vendored/puppet/lib/puppet/provider/cisco.rb +0 -9
- data/vendored/puppet/lib/puppet/provider/computer/computer.rb +0 -20
- data/vendored/puppet/lib/puppet/provider/host/parsed.rb +0 -46
- data/vendored/puppet/lib/puppet/provider/interface/cisco.rb +0 -27
- data/vendored/puppet/lib/puppet/provider/macauthorization/macauthorization.rb +0 -298
- data/vendored/puppet/lib/puppet/provider/mcx/mcxcontent.rb +0 -173
- data/vendored/puppet/lib/puppet/provider/mount/parsed.rb +0 -282
- data/vendored/puppet/lib/puppet/provider/mount.rb +0 -76
- data/vendored/puppet/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +0 -590
- data/vendored/puppet/lib/puppet/provider/selboolean/getsetsebool.rb +0 -47
- data/vendored/puppet/lib/puppet/provider/selmodule/semodule.rb +0 -140
- data/vendored/puppet/lib/puppet/provider/ssh_authorized_key/parsed.rb +0 -105
- data/vendored/puppet/lib/puppet/provider/sshkey/parsed.rb +0 -50
- data/vendored/puppet/lib/puppet/provider/vlan/cisco.rb +0 -28
- data/vendored/puppet/lib/puppet/provider/yumrepo/inifile.rb +0 -315
- data/vendored/puppet/lib/puppet/type/augeas.rb +0 -211
- data/vendored/puppet/lib/puppet/type/computer.rb +0 -66
- data/vendored/puppet/lib/puppet/type/host.rb +0 -95
- data/vendored/puppet/lib/puppet/type/interface.rb +0 -121
- data/vendored/puppet/lib/puppet/type/k5login.rb +0 -165
- data/vendored/puppet/lib/puppet/type/macauthorization.rb +0 -167
- data/vendored/puppet/lib/puppet/type/mcx.rb +0 -98
- data/vendored/puppet/lib/puppet/type/mount.rb +0 -314
- data/vendored/puppet/lib/puppet/type/router.rb +0 -17
- data/vendored/puppet/lib/puppet/type/scheduled_task.rb +0 -183
- data/vendored/puppet/lib/puppet/type/selboolean.rb +0 -26
- data/vendored/puppet/lib/puppet/type/selmodule.rb +0 -59
- data/vendored/puppet/lib/puppet/type/ssh_authorized_key.rb +0 -143
- data/vendored/puppet/lib/puppet/type/sshkey.rb +0 -83
- data/vendored/puppet/lib/puppet/type/vlan.rb +0 -26
- data/vendored/puppet/lib/puppet/type/yumrepo.rb +0 -430
- data/vendored/puppet/lib/puppet/util/network_device/cisco/device.rb +0 -285
- data/vendored/puppet/lib/puppet/util/network_device/cisco/facts.rb +0 -72
- data/vendored/puppet/lib/puppet/util/network_device/cisco/interface.rb +0 -94
- data/vendored/puppet/lib/puppet/util/network_device/cisco.rb +0 -4
- data/vendored/puppet/lib/puppet/util/network_device/ipcalc.rb +0 -68
- data/vendored/puppet/lib/puppet/util/network_device/transport/ssh.rb +0 -126
- data/vendored/puppet/lib/puppet/util/network_device/transport/telnet.rb +0 -47
- data/vendored/puppet/lib/puppet/util/windows/taskscheduler.rb +0 -1267
@@ -1,1267 +0,0 @@
|
|
1
|
-
require 'puppet/util/windows'
|
2
|
-
|
3
|
-
# The Win32 module serves as a namespace only
|
4
|
-
module Win32
|
5
|
-
# The TaskScheduler class encapsulates taskscheduler settings and behavior
|
6
|
-
class TaskScheduler
|
7
|
-
include Puppet::Util::Windows::String
|
8
|
-
|
9
|
-
require 'ffi'
|
10
|
-
extend FFI::Library
|
11
|
-
|
12
|
-
# The error class raised if any task scheduler specific calls fail.
|
13
|
-
class Error < Puppet::Util::Windows::Error; end
|
14
|
-
|
15
|
-
class << self
|
16
|
-
attr_accessor :com_initialized
|
17
|
-
end
|
18
|
-
|
19
|
-
# :stopdoc:
|
20
|
-
TASK_TIME_TRIGGER_ONCE = :TASK_TIME_TRIGGER_ONCE
|
21
|
-
TASK_TIME_TRIGGER_DAILY = :TASK_TIME_TRIGGER_DAILY
|
22
|
-
TASK_TIME_TRIGGER_WEEKLY = :TASK_TIME_TRIGGER_WEEKLY
|
23
|
-
TASK_TIME_TRIGGER_MONTHLYDATE = :TASK_TIME_TRIGGER_MONTHLYDATE
|
24
|
-
TASK_TIME_TRIGGER_MONTHLYDOW = :TASK_TIME_TRIGGER_MONTHLYDOW
|
25
|
-
TASK_EVENT_TRIGGER_ON_IDLE = :TASK_EVENT_TRIGGER_ON_IDLE
|
26
|
-
TASK_EVENT_TRIGGER_AT_SYSTEMSTART = :TASK_EVENT_TRIGGER_AT_SYSTEMSTART
|
27
|
-
TASK_EVENT_TRIGGER_AT_LOGON = :TASK_EVENT_TRIGGER_AT_LOGON
|
28
|
-
|
29
|
-
TASK_SUNDAY = 0x1
|
30
|
-
TASK_MONDAY = 0x2
|
31
|
-
TASK_TUESDAY = 0x4
|
32
|
-
TASK_WEDNESDAY = 0x8
|
33
|
-
TASK_THURSDAY = 0x10
|
34
|
-
TASK_FRIDAY = 0x20
|
35
|
-
TASK_SATURDAY = 0x40
|
36
|
-
TASK_FIRST_WEEK = 1
|
37
|
-
TASK_SECOND_WEEK = 2
|
38
|
-
TASK_THIRD_WEEK = 3
|
39
|
-
TASK_FOURTH_WEEK = 4
|
40
|
-
TASK_LAST_WEEK = 5
|
41
|
-
TASK_JANUARY = 0x1
|
42
|
-
TASK_FEBRUARY = 0x2
|
43
|
-
TASK_MARCH = 0x4
|
44
|
-
TASK_APRIL = 0x8
|
45
|
-
TASK_MAY = 0x10
|
46
|
-
TASK_JUNE = 0x20
|
47
|
-
TASK_JULY = 0x40
|
48
|
-
TASK_AUGUST = 0x80
|
49
|
-
TASK_SEPTEMBER = 0x100
|
50
|
-
TASK_OCTOBER = 0x200
|
51
|
-
TASK_NOVEMBER = 0x400
|
52
|
-
TASK_DECEMBER = 0x800
|
53
|
-
|
54
|
-
TASK_FLAG_INTERACTIVE = 0x1
|
55
|
-
TASK_FLAG_DELETE_WHEN_DONE = 0x2
|
56
|
-
TASK_FLAG_DISABLED = 0x4
|
57
|
-
TASK_FLAG_START_ONLY_IF_IDLE = 0x10
|
58
|
-
TASK_FLAG_KILL_ON_IDLE_END = 0x20
|
59
|
-
TASK_FLAG_DONT_START_IF_ON_BATTERIES = 0x40
|
60
|
-
TASK_FLAG_KILL_IF_GOING_ON_BATTERIES = 0x80
|
61
|
-
TASK_FLAG_RUN_ONLY_IF_DOCKED = 0x100
|
62
|
-
TASK_FLAG_HIDDEN = 0x200
|
63
|
-
TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET = 0x400
|
64
|
-
TASK_FLAG_RESTART_ON_IDLE_RESUME = 0x800
|
65
|
-
TASK_FLAG_SYSTEM_REQUIRED = 0x1000
|
66
|
-
TASK_FLAG_RUN_ONLY_IF_LOGGED_ON = 0x2000
|
67
|
-
TASK_TRIGGER_FLAG_HAS_END_DATE = 0x1
|
68
|
-
TASK_TRIGGER_FLAG_KILL_AT_DURATION_END = 0x2
|
69
|
-
TASK_TRIGGER_FLAG_DISABLED = 0x4
|
70
|
-
|
71
|
-
TASK_MAX_RUN_TIMES = 1440
|
72
|
-
TASKS_TO_RETRIEVE = 5
|
73
|
-
|
74
|
-
# COM
|
75
|
-
|
76
|
-
CLSID_CTask = FFI::WIN32::GUID['148BD520-A2AB-11CE-B11F-00AA00530503']
|
77
|
-
IID_ITask = FFI::WIN32::GUID['148BD524-A2AB-11CE-B11F-00AA00530503']
|
78
|
-
IID_IPersistFile = FFI::WIN32::GUID['0000010b-0000-0000-C000-000000000046']
|
79
|
-
|
80
|
-
SCHED_S_TASK_READY = 0x00041300
|
81
|
-
SCHED_S_TASK_RUNNING = 0x00041301
|
82
|
-
SCHED_S_TASK_HAS_NOT_RUN = 0x00041303
|
83
|
-
SCHED_S_TASK_NOT_SCHEDULED = 0x00041305
|
84
|
-
# HRESULT error codes
|
85
|
-
# https://blogs.msdn.com/b/eldar/archive/2007/04/03/a-lot-of-hresult-codes.aspx
|
86
|
-
# in Ruby, an 0x8XXXXXXX style HRESULT can be resolved to 2s complement
|
87
|
-
# by using "0x8XXXXXXX".to_i(16) - - 0x100000000
|
88
|
-
SCHED_E_ACCOUNT_INFORMATION_NOT_SET = -2147216625 # 0x8004130F
|
89
|
-
SCHED_E_NO_SECURITY_SERVICES = -2147216622 # 0x80041312
|
90
|
-
# No mapping between account names and security IDs was done.
|
91
|
-
ERROR_NONE_MAPPED = -2147023564 # 0x80070534 WIN32 Error CODE 1332 (0x534)
|
92
|
-
|
93
|
-
# :startdoc:
|
94
|
-
|
95
|
-
# Shorthand constants
|
96
|
-
IDLE = Puppet::Util::Windows::Process::IDLE_PRIORITY_CLASS
|
97
|
-
NORMAL = Puppet::Util::Windows::Process::NORMAL_PRIORITY_CLASS
|
98
|
-
HIGH = Puppet::Util::Windows::Process::HIGH_PRIORITY_CLASS
|
99
|
-
REALTIME = Puppet::Util::Windows::Process::REALTIME_PRIORITY_CLASS
|
100
|
-
BELOW_NORMAL = Puppet::Util::Windows::Process::BELOW_NORMAL_PRIORITY_CLASS
|
101
|
-
ABOVE_NORMAL = Puppet::Util::Windows::Process::ABOVE_NORMAL_PRIORITY_CLASS
|
102
|
-
|
103
|
-
ONCE = TASK_TIME_TRIGGER_ONCE
|
104
|
-
DAILY = TASK_TIME_TRIGGER_DAILY
|
105
|
-
WEEKLY = TASK_TIME_TRIGGER_WEEKLY
|
106
|
-
MONTHLYDATE = TASK_TIME_TRIGGER_MONTHLYDATE
|
107
|
-
MONTHLYDOW = TASK_TIME_TRIGGER_MONTHLYDOW
|
108
|
-
|
109
|
-
ON_IDLE = TASK_EVENT_TRIGGER_ON_IDLE
|
110
|
-
AT_SYSTEMSTART = TASK_EVENT_TRIGGER_AT_SYSTEMSTART
|
111
|
-
AT_LOGON = TASK_EVENT_TRIGGER_AT_LOGON
|
112
|
-
FIRST_WEEK = TASK_FIRST_WEEK
|
113
|
-
SECOND_WEEK = TASK_SECOND_WEEK
|
114
|
-
THIRD_WEEK = TASK_THIRD_WEEK
|
115
|
-
FOURTH_WEEK = TASK_FOURTH_WEEK
|
116
|
-
LAST_WEEK = TASK_LAST_WEEK
|
117
|
-
SUNDAY = TASK_SUNDAY
|
118
|
-
MONDAY = TASK_MONDAY
|
119
|
-
TUESDAY = TASK_TUESDAY
|
120
|
-
WEDNESDAY = TASK_WEDNESDAY
|
121
|
-
THURSDAY = TASK_THURSDAY
|
122
|
-
FRIDAY = TASK_FRIDAY
|
123
|
-
SATURDAY = TASK_SATURDAY
|
124
|
-
JANUARY = TASK_JANUARY
|
125
|
-
FEBRUARY = TASK_FEBRUARY
|
126
|
-
MARCH = TASK_MARCH
|
127
|
-
APRIL = TASK_APRIL
|
128
|
-
MAY = TASK_MAY
|
129
|
-
JUNE = TASK_JUNE
|
130
|
-
JULY = TASK_JULY
|
131
|
-
AUGUST = TASK_AUGUST
|
132
|
-
SEPTEMBER = TASK_SEPTEMBER
|
133
|
-
OCTOBER = TASK_OCTOBER
|
134
|
-
NOVEMBER = TASK_NOVEMBER
|
135
|
-
DECEMBER = TASK_DECEMBER
|
136
|
-
|
137
|
-
INTERACTIVE = TASK_FLAG_INTERACTIVE
|
138
|
-
DELETE_WHEN_DONE = TASK_FLAG_DELETE_WHEN_DONE
|
139
|
-
DISABLED = TASK_FLAG_DISABLED
|
140
|
-
START_ONLY_IF_IDLE = TASK_FLAG_START_ONLY_IF_IDLE
|
141
|
-
KILL_ON_IDLE_END = TASK_FLAG_KILL_ON_IDLE_END
|
142
|
-
DONT_START_IF_ON_BATTERIES = TASK_FLAG_DONT_START_IF_ON_BATTERIES
|
143
|
-
KILL_IF_GOING_ON_BATTERIES = TASK_FLAG_KILL_IF_GOING_ON_BATTERIES
|
144
|
-
RUN_ONLY_IF_DOCKED = TASK_FLAG_RUN_ONLY_IF_DOCKED
|
145
|
-
HIDDEN = TASK_FLAG_HIDDEN
|
146
|
-
RUN_IF_CONNECTED_TO_INTERNET = TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET
|
147
|
-
RESTART_ON_IDLE_RESUME = TASK_FLAG_RESTART_ON_IDLE_RESUME
|
148
|
-
SYSTEM_REQUIRED = TASK_FLAG_SYSTEM_REQUIRED
|
149
|
-
RUN_ONLY_IF_LOGGED_ON = TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
|
150
|
-
|
151
|
-
FLAG_HAS_END_DATE = TASK_TRIGGER_FLAG_HAS_END_DATE
|
152
|
-
FLAG_KILL_AT_DURATION_END = TASK_TRIGGER_FLAG_KILL_AT_DURATION_END
|
153
|
-
FLAG_DISABLED = TASK_TRIGGER_FLAG_DISABLED
|
154
|
-
|
155
|
-
MAX_RUN_TIMES = TASK_MAX_RUN_TIMES
|
156
|
-
|
157
|
-
# unfortunately MSTask.h does not specify the limits for any settings
|
158
|
-
# so these were determined with some experimentation
|
159
|
-
# if values too large are written, its suspected there may be internal
|
160
|
-
# limits may be exceeded, corrupting the job
|
161
|
-
# used for max application name and path values
|
162
|
-
MAX_PATH = 260
|
163
|
-
# UNLEN from lmcons.h is 256
|
164
|
-
# https://technet.microsoft.com/it-it/library/bb726984(en-us).aspx specifies 104
|
165
|
-
MAX_ACCOUNT_LENGTH = 256
|
166
|
-
# command line max length is limited to 8191, choose something high but still enough that we don't blow out CLI
|
167
|
-
MAX_PARAMETERS_LENGTH = 4096
|
168
|
-
# in testing, this value could be set to a length of 99999, but saving / loading the task failed
|
169
|
-
MAX_COMMENT_LENGTH = 8192
|
170
|
-
|
171
|
-
# Returns a new TaskScheduler object. If a work_item (and possibly the
|
172
|
-
# the trigger) are passed as arguments then a new work item is created and
|
173
|
-
# associated with that trigger, although you can still activate other tasks
|
174
|
-
# with the same handle.
|
175
|
-
#
|
176
|
-
# This is really just a bit of convenience. Passing arguments to the
|
177
|
-
# constructor is the same as calling TaskScheduler.new plus
|
178
|
-
# TaskScheduler#new_work_item.
|
179
|
-
#
|
180
|
-
def initialize(work_item=nil, trigger=nil)
|
181
|
-
@pITS = nil
|
182
|
-
@pITask = nil
|
183
|
-
|
184
|
-
if ! self.class.com_initialized
|
185
|
-
Puppet::Util::Windows::COM.InitializeCom()
|
186
|
-
self.class.com_initialized = true
|
187
|
-
end
|
188
|
-
|
189
|
-
@pITS = COM::TaskScheduler.new
|
190
|
-
at_exit do
|
191
|
-
begin
|
192
|
-
@pITS.Release if @pITS && !@pITS.null?
|
193
|
-
@pITS = nil
|
194
|
-
rescue
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
if work_item
|
199
|
-
if trigger
|
200
|
-
raise TypeError unless trigger.is_a?(Hash)
|
201
|
-
new_work_item(work_item, trigger)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
# Returns an array of scheduled task names.
|
207
|
-
#
|
208
|
-
def enum
|
209
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
210
|
-
array = []
|
211
|
-
|
212
|
-
@pITS.UseInstance(COM::EnumWorkItems, :Enum) do |pIEnum|
|
213
|
-
FFI::MemoryPointer.new(:pointer) do |names_array_ptr_ptr|
|
214
|
-
FFI::MemoryPointer.new(:win32_ulong) do |fetched_count_ptr|
|
215
|
-
# awkward usage, if number requested is available, returns S_OK (0), or if less were returned returns S_FALSE (1)
|
216
|
-
while (pIEnum.Next(TASKS_TO_RETRIEVE, names_array_ptr_ptr, fetched_count_ptr) >= Puppet::Util::Windows::COM::S_OK)
|
217
|
-
count = fetched_count_ptr.read_win32_ulong
|
218
|
-
break if count == 0
|
219
|
-
|
220
|
-
names_array_ptr_ptr.read_com_memory_pointer do |names_array_ptr|
|
221
|
-
# iterate over the array of pointers
|
222
|
-
name_ptr_ptr = FFI::Pointer.new(:pointer, names_array_ptr)
|
223
|
-
for i in 0 ... count
|
224
|
-
name_ptr_ptr[i].read_com_memory_pointer do |name_ptr|
|
225
|
-
array << name_ptr.read_arbitrary_wide_string_up_to(MAX_PATH)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
array
|
235
|
-
end
|
236
|
-
|
237
|
-
alias :tasks :enum
|
238
|
-
|
239
|
-
# Activate the specified task.
|
240
|
-
#
|
241
|
-
def activate(task)
|
242
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
243
|
-
raise TypeError unless task.is_a?(String)
|
244
|
-
|
245
|
-
FFI::MemoryPointer.new(:pointer) do |ptr|
|
246
|
-
@pITS.Activate(wide_string(task), IID_ITask, ptr)
|
247
|
-
|
248
|
-
reset_current_task
|
249
|
-
@pITask = COM::Task.new(ptr.read_pointer)
|
250
|
-
end
|
251
|
-
|
252
|
-
@pITask
|
253
|
-
end
|
254
|
-
|
255
|
-
# Delete the specified task name.
|
256
|
-
#
|
257
|
-
def delete(task)
|
258
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
259
|
-
raise TypeError unless task.is_a?(String)
|
260
|
-
|
261
|
-
@pITS.Delete(wide_string(task))
|
262
|
-
|
263
|
-
true
|
264
|
-
end
|
265
|
-
|
266
|
-
# Execute the current task.
|
267
|
-
#
|
268
|
-
def run
|
269
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
270
|
-
|
271
|
-
@pITask.Run
|
272
|
-
end
|
273
|
-
|
274
|
-
# Saves the current task. Tasks must be saved before they can be activated.
|
275
|
-
# The .job file itself is typically stored in the C:\WINDOWS\Tasks folder.
|
276
|
-
#
|
277
|
-
# If +file+ (an absolute path) is specified then the job is saved to that
|
278
|
-
# file instead. A '.job' extension is recommended but not enforced.
|
279
|
-
#
|
280
|
-
def save(file = nil)
|
281
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
282
|
-
raise Error.new(_('Account information must be set on the current task to save it properly.')) if !@account_information_set
|
283
|
-
|
284
|
-
reset = true
|
285
|
-
|
286
|
-
begin
|
287
|
-
@pITask.QueryInstance(COM::PersistFile) do |pIPersistFile|
|
288
|
-
wide_file = wide_string(file)
|
289
|
-
pIPersistFile.Save(wide_file, 1)
|
290
|
-
pIPersistFile.SaveCompleted(wide_file)
|
291
|
-
end
|
292
|
-
rescue
|
293
|
-
reset = false
|
294
|
-
ensure
|
295
|
-
reset_current_task if reset
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
# Terminate the current task.
|
300
|
-
#
|
301
|
-
def terminate
|
302
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
303
|
-
|
304
|
-
@pITask.Terminate
|
305
|
-
end
|
306
|
-
|
307
|
-
# Set the host on which the various TaskScheduler methods will execute.
|
308
|
-
#
|
309
|
-
def machine=(host)
|
310
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
311
|
-
raise TypeError unless host.is_a?(String)
|
312
|
-
|
313
|
-
@pITS.SetTargetComputer(wide_string(host))
|
314
|
-
|
315
|
-
host
|
316
|
-
end
|
317
|
-
|
318
|
-
alias :host= :machine=
|
319
|
-
|
320
|
-
# Sets the +user+ and +password+ for the given task. If the user and
|
321
|
-
# password are set properly then true is returned.
|
322
|
-
#
|
323
|
-
# In some cases the job may be created, but the account information was
|
324
|
-
# bad. In this case the task is created but a warning is generated and
|
325
|
-
# false is returned.
|
326
|
-
#
|
327
|
-
# Note that if intending to use SYSTEM, specify an empty user and nil password
|
328
|
-
#
|
329
|
-
# Calling task.set_account_information('SYSTEM', nil) will generally not
|
330
|
-
# work, except for one special case where flags are also set like:
|
331
|
-
# task.flags = Win32::TaskScheduler::TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
|
332
|
-
#
|
333
|
-
# This must be done prior to the 1st save() call for the task to be
|
334
|
-
# properly registered and visible through the MMC snap-in / schtasks.exe
|
335
|
-
#
|
336
|
-
def set_account_information(user, password)
|
337
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
338
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
339
|
-
|
340
|
-
bool = false
|
341
|
-
|
342
|
-
begin
|
343
|
-
if (user.nil? || user=="") && (password.nil? || password=="")
|
344
|
-
@pITask.SetAccountInformation(wide_string(""), FFI::Pointer::NULL)
|
345
|
-
else
|
346
|
-
if user.length > MAX_ACCOUNT_LENGTH
|
347
|
-
raise Error.new(_("User has exceeded maximum allowed length %{max}") % { max: MAX_ACCOUNT_LENGTH })
|
348
|
-
end
|
349
|
-
user = wide_string(user)
|
350
|
-
password = wide_string(password)
|
351
|
-
@pITask.SetAccountInformation(user, password)
|
352
|
-
end
|
353
|
-
|
354
|
-
@account_information_set = true
|
355
|
-
bool = true
|
356
|
-
rescue Puppet::Util::Windows::Error => e
|
357
|
-
raise e unless e.code == SCHED_E_ACCOUNT_INFORMATION_NOT_SET
|
358
|
-
|
359
|
-
warn _('job created, but password was invalid')
|
360
|
-
end
|
361
|
-
|
362
|
-
bool
|
363
|
-
end
|
364
|
-
|
365
|
-
# Returns the user associated with the task or nil if no user has yet
|
366
|
-
# been associated with the task.
|
367
|
-
#
|
368
|
-
def account_information
|
369
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
370
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
371
|
-
|
372
|
-
# default under certain failures
|
373
|
-
user = nil
|
374
|
-
|
375
|
-
begin
|
376
|
-
FFI::MemoryPointer.new(:pointer) do |ptr|
|
377
|
-
@pITask.GetAccountInformation(ptr)
|
378
|
-
ptr.read_com_memory_pointer do |str_ptr|
|
379
|
-
user = str_ptr.read_arbitrary_wide_string_up_to(MAX_ACCOUNT_LENGTH) if ! str_ptr.null?
|
380
|
-
end
|
381
|
-
end
|
382
|
-
rescue Puppet::Util::Windows::Error => e
|
383
|
-
raise e unless e.code == SCHED_E_ACCOUNT_INFORMATION_NOT_SET ||
|
384
|
-
e.code == SCHED_E_NO_SECURITY_SERVICES ||
|
385
|
-
e.code == ERROR_NONE_MAPPED
|
386
|
-
end
|
387
|
-
|
388
|
-
user
|
389
|
-
end
|
390
|
-
|
391
|
-
# Returns the name of the application associated with the task.
|
392
|
-
#
|
393
|
-
def application_name
|
394
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
395
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
396
|
-
|
397
|
-
app = nil
|
398
|
-
|
399
|
-
FFI::MemoryPointer.new(:pointer) do |ptr|
|
400
|
-
@pITask.GetApplicationName(ptr)
|
401
|
-
|
402
|
-
ptr.read_com_memory_pointer do |str_ptr|
|
403
|
-
app = str_ptr.read_arbitrary_wide_string_up_to(MAX_PATH) if ! str_ptr.null?
|
404
|
-
end
|
405
|
-
end
|
406
|
-
|
407
|
-
app
|
408
|
-
end
|
409
|
-
|
410
|
-
# Sets the application name associated with the task.
|
411
|
-
#
|
412
|
-
def application_name=(app)
|
413
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
414
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
415
|
-
raise TypeError unless app.is_a?(String)
|
416
|
-
|
417
|
-
# the application name is written to a .job file on disk, so is subject to path limitations
|
418
|
-
if app.length > MAX_PATH
|
419
|
-
raise Error.new(_("Application name has exceeded maximum allowed length %{max}") % { max: MAX_PATH })
|
420
|
-
end
|
421
|
-
@pITask.SetApplicationName(wide_string(app))
|
422
|
-
|
423
|
-
app
|
424
|
-
end
|
425
|
-
|
426
|
-
# Returns the command line parameters for the task.
|
427
|
-
#
|
428
|
-
def parameters
|
429
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
430
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
431
|
-
|
432
|
-
param = nil
|
433
|
-
|
434
|
-
FFI::MemoryPointer.new(:pointer) do |ptr|
|
435
|
-
@pITask.GetParameters(ptr)
|
436
|
-
|
437
|
-
ptr.read_com_memory_pointer do |str_ptr|
|
438
|
-
param = str_ptr.read_arbitrary_wide_string_up_to(MAX_PARAMETERS_LENGTH) if ! str_ptr.null?
|
439
|
-
end
|
440
|
-
end
|
441
|
-
|
442
|
-
param
|
443
|
-
end
|
444
|
-
|
445
|
-
# Sets the parameters for the task. These parameters are passed as command
|
446
|
-
# line arguments to the application the task will run. To clear the command
|
447
|
-
# line parameters set it to an empty string.
|
448
|
-
#
|
449
|
-
def parameters=(param)
|
450
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
451
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
452
|
-
raise TypeError unless param.is_a?(String)
|
453
|
-
|
454
|
-
if param.length > MAX_PARAMETERS_LENGTH
|
455
|
-
raise Error.new(_("Parameters has exceeded maximum allowed length %{max}") % { max: MAX_PARAMETERS_LENGTH })
|
456
|
-
end
|
457
|
-
|
458
|
-
@pITask.SetParameters(wide_string(param))
|
459
|
-
|
460
|
-
param
|
461
|
-
end
|
462
|
-
|
463
|
-
# Returns the working directory for the task.
|
464
|
-
#
|
465
|
-
def working_directory
|
466
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
467
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
468
|
-
|
469
|
-
dir = nil
|
470
|
-
|
471
|
-
FFI::MemoryPointer.new(:pointer) do |ptr|
|
472
|
-
@pITask.GetWorkingDirectory(ptr)
|
473
|
-
|
474
|
-
ptr.read_com_memory_pointer do |str_ptr|
|
475
|
-
dir = str_ptr.read_arbitrary_wide_string_up_to(MAX_PATH) if ! str_ptr.null?
|
476
|
-
end
|
477
|
-
end
|
478
|
-
|
479
|
-
dir
|
480
|
-
end
|
481
|
-
|
482
|
-
# Sets the working directory for the task.
|
483
|
-
#
|
484
|
-
def working_directory=(dir)
|
485
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
486
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
487
|
-
raise TypeError unless dir.is_a?(String)
|
488
|
-
|
489
|
-
if dir.length > MAX_PATH
|
490
|
-
raise Error.new(_("Working directory has exceeded maximum allowed length %{max}") % { max: MAX_PATH })
|
491
|
-
end
|
492
|
-
|
493
|
-
@pITask.SetWorkingDirectory(wide_string(dir))
|
494
|
-
|
495
|
-
dir
|
496
|
-
end
|
497
|
-
|
498
|
-
# Returns the task's priority level. Possible values are 'idle',
|
499
|
-
# 'normal', 'high', 'realtime', 'below_normal', 'above_normal',
|
500
|
-
# and 'unknown'.
|
501
|
-
#
|
502
|
-
def priority
|
503
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
504
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
505
|
-
|
506
|
-
priority_name = ''
|
507
|
-
|
508
|
-
FFI::MemoryPointer.new(:dword, 1) do |ptr|
|
509
|
-
@pITask.GetPriority(ptr)
|
510
|
-
|
511
|
-
pri = ptr.read_dword
|
512
|
-
if (pri & IDLE) != 0
|
513
|
-
priority_name = 'idle'
|
514
|
-
elsif (pri & NORMAL) != 0
|
515
|
-
priority_name = 'normal'
|
516
|
-
elsif (pri & HIGH) != 0
|
517
|
-
priority_name = 'high'
|
518
|
-
elsif (pri & REALTIME) != 0
|
519
|
-
priority_name = 'realtime'
|
520
|
-
elsif (pri & BELOW_NORMAL) != 0
|
521
|
-
priority_name = 'below_normal'
|
522
|
-
elsif (pri & ABOVE_NORMAL) != 0
|
523
|
-
priority_name = 'above_normal'
|
524
|
-
else
|
525
|
-
priority_name = 'unknown'
|
526
|
-
end
|
527
|
-
end
|
528
|
-
|
529
|
-
priority_name
|
530
|
-
end
|
531
|
-
|
532
|
-
# Sets the priority of the task. The +priority+ should be a numeric
|
533
|
-
# priority constant value.
|
534
|
-
#
|
535
|
-
def priority=(priority)
|
536
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
537
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
538
|
-
raise TypeError unless priority.is_a?(Numeric)
|
539
|
-
|
540
|
-
@pITask.SetPriority(priority)
|
541
|
-
|
542
|
-
priority
|
543
|
-
end
|
544
|
-
|
545
|
-
# Creates a new work item (scheduled job) with the given +trigger+. The
|
546
|
-
# trigger variable is a hash of options that define when the scheduled
|
547
|
-
# job should run.
|
548
|
-
#
|
549
|
-
def new_work_item(task, trigger)
|
550
|
-
raise TypeError unless trigger.is_a?(Hash)
|
551
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
552
|
-
|
553
|
-
# I'm working around github issue #1 here.
|
554
|
-
enum.each{ |name|
|
555
|
-
if name.downcase == task.downcase + '.job'
|
556
|
-
raise Error.new(_("task '%{task}' already exists") % { task: task })
|
557
|
-
end
|
558
|
-
}
|
559
|
-
|
560
|
-
FFI::MemoryPointer.new(:pointer) do |ptr|
|
561
|
-
@pITS.NewWorkItem(wide_string(task), CLSID_CTask, IID_ITask, ptr)
|
562
|
-
|
563
|
-
reset_current_task
|
564
|
-
@pITask = COM::Task.new(ptr.read_pointer)
|
565
|
-
|
566
|
-
FFI::MemoryPointer.new(:word, 1) do |trigger_index_ptr|
|
567
|
-
# Without the 'enum.include?' check above the code segfaults here if the
|
568
|
-
# task already exists. This should probably be handled properly instead
|
569
|
-
# of simply avoiding the issue.
|
570
|
-
|
571
|
-
@pITask.UseInstance(COM::TaskTrigger, :CreateTrigger, trigger_index_ptr) do |pITaskTrigger|
|
572
|
-
populate_trigger(pITaskTrigger, trigger)
|
573
|
-
end
|
574
|
-
end
|
575
|
-
end
|
576
|
-
|
577
|
-
# preload task with the SYSTEM account
|
578
|
-
# empty string '' means 'SYSTEM' per MSDN, so default it
|
579
|
-
# given an account is necessary for creation of a task
|
580
|
-
# note that a user may set SYSTEM explicitly, but that has problems
|
581
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa381276(v=vs.85).aspx
|
582
|
-
set_account_information('', nil)
|
583
|
-
|
584
|
-
@pITask
|
585
|
-
end
|
586
|
-
|
587
|
-
alias :new_task :new_work_item
|
588
|
-
|
589
|
-
# Returns the number of triggers associated with the active task.
|
590
|
-
#
|
591
|
-
def trigger_count
|
592
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
593
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
594
|
-
|
595
|
-
count = 0
|
596
|
-
|
597
|
-
FFI::MemoryPointer.new(:word, 1) do |ptr|
|
598
|
-
@pITask.GetTriggerCount(ptr)
|
599
|
-
count = ptr.read_word
|
600
|
-
end
|
601
|
-
|
602
|
-
count
|
603
|
-
end
|
604
|
-
|
605
|
-
# Deletes the trigger at the specified index.
|
606
|
-
#
|
607
|
-
def delete_trigger(index)
|
608
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
609
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
610
|
-
|
611
|
-
@pITask.DeleteTrigger(index)
|
612
|
-
index
|
613
|
-
end
|
614
|
-
|
615
|
-
# Returns a hash that describes the trigger at the given index for the
|
616
|
-
# current task.
|
617
|
-
#
|
618
|
-
def trigger(index)
|
619
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
620
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
621
|
-
|
622
|
-
trigger = {}
|
623
|
-
|
624
|
-
@pITask.UseInstance(COM::TaskTrigger, :GetTrigger, index) do |pITaskTrigger|
|
625
|
-
FFI::MemoryPointer.new(COM::TASK_TRIGGER.size) do |task_trigger_ptr|
|
626
|
-
pITaskTrigger.GetTrigger(task_trigger_ptr)
|
627
|
-
trigger = populate_hash_from_trigger(COM::TASK_TRIGGER.new(task_trigger_ptr))
|
628
|
-
end
|
629
|
-
end
|
630
|
-
|
631
|
-
trigger
|
632
|
-
end
|
633
|
-
|
634
|
-
# Sets the trigger for the currently active task.
|
635
|
-
#
|
636
|
-
def trigger=(trigger)
|
637
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
638
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
639
|
-
raise TypeError unless trigger.is_a?(Hash)
|
640
|
-
|
641
|
-
FFI::MemoryPointer.new(:word, 1) do |trigger_index_ptr|
|
642
|
-
# Without the 'enum.include?' check above the code segfaults here if the
|
643
|
-
# task already exists. This should probably be handled properly instead
|
644
|
-
# of simply avoiding the issue.
|
645
|
-
|
646
|
-
@pITask.UseInstance(COM::TaskTrigger, :CreateTrigger, trigger_index_ptr) do |pITaskTrigger|
|
647
|
-
populate_trigger(pITaskTrigger, trigger)
|
648
|
-
end
|
649
|
-
end
|
650
|
-
|
651
|
-
trigger
|
652
|
-
end
|
653
|
-
|
654
|
-
# Adds a trigger at the specified index.
|
655
|
-
#
|
656
|
-
def add_trigger(index, trigger)
|
657
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
658
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
659
|
-
raise TypeError unless trigger.is_a?(Hash)
|
660
|
-
|
661
|
-
@pITask.UseInstance(COM::TaskTrigger, :GetTrigger, index) do |pITaskTrigger|
|
662
|
-
populate_trigger(pITaskTrigger, trigger)
|
663
|
-
end
|
664
|
-
end
|
665
|
-
|
666
|
-
# Returns the flags (integer) that modify the behavior of the work item. You
|
667
|
-
# must OR the return value to determine the flags yourself.
|
668
|
-
#
|
669
|
-
def flags
|
670
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
671
|
-
|
672
|
-
flags = 0
|
673
|
-
|
674
|
-
FFI::MemoryPointer.new(:dword, 1) do |ptr|
|
675
|
-
@pITask.GetFlags(ptr)
|
676
|
-
flags = ptr.read_dword
|
677
|
-
end
|
678
|
-
|
679
|
-
flags
|
680
|
-
end
|
681
|
-
|
682
|
-
# Sets an OR'd value of flags that modify the behavior of the work item.
|
683
|
-
#
|
684
|
-
def flags=(flags)
|
685
|
-
raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
|
686
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
687
|
-
|
688
|
-
@pITask.SetFlags(flags)
|
689
|
-
flags
|
690
|
-
end
|
691
|
-
|
692
|
-
# Returns the status of the currently active task. Possible values are
|
693
|
-
# 'ready', 'running', 'not scheduled' or 'unknown'.
|
694
|
-
#
|
695
|
-
def status
|
696
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
697
|
-
|
698
|
-
st = nil
|
699
|
-
|
700
|
-
FFI::MemoryPointer.new(:hresult, 1) do |ptr|
|
701
|
-
@pITask.GetStatus(ptr)
|
702
|
-
st = ptr.read_hresult
|
703
|
-
end
|
704
|
-
|
705
|
-
case st
|
706
|
-
when SCHED_S_TASK_READY
|
707
|
-
status = 'ready'
|
708
|
-
when SCHED_S_TASK_RUNNING
|
709
|
-
status = 'running'
|
710
|
-
when SCHED_S_TASK_NOT_SCHEDULED
|
711
|
-
status = 'not scheduled'
|
712
|
-
else
|
713
|
-
status = 'unknown'
|
714
|
-
end
|
715
|
-
|
716
|
-
status
|
717
|
-
end
|
718
|
-
|
719
|
-
# Returns the exit code from the last scheduled run.
|
720
|
-
#
|
721
|
-
def exit_code
|
722
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
723
|
-
|
724
|
-
status = 0
|
725
|
-
|
726
|
-
begin
|
727
|
-
FFI::MemoryPointer.new(:dword, 1) do |ptr|
|
728
|
-
@pITask.GetExitCode(ptr)
|
729
|
-
status = ptr.read_dword
|
730
|
-
end
|
731
|
-
rescue Puppet::Util::Windows::Error => e
|
732
|
-
raise e unless e.code == SCHED_S_TASK_HAS_NOT_RUN
|
733
|
-
end
|
734
|
-
|
735
|
-
status
|
736
|
-
end
|
737
|
-
|
738
|
-
# Returns the comment associated with the task, if any.
|
739
|
-
#
|
740
|
-
def comment
|
741
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
742
|
-
|
743
|
-
comment = nil
|
744
|
-
|
745
|
-
FFI::MemoryPointer.new(:pointer) do |ptr|
|
746
|
-
@pITask.GetComment(ptr)
|
747
|
-
|
748
|
-
ptr.read_com_memory_pointer do |str_ptr|
|
749
|
-
comment = str_ptr.read_arbitrary_wide_string_up_to(MAX_COMMENT_LENGTH) if ! str_ptr.null?
|
750
|
-
end
|
751
|
-
end
|
752
|
-
|
753
|
-
comment
|
754
|
-
end
|
755
|
-
|
756
|
-
# Sets the comment for the task.
|
757
|
-
#
|
758
|
-
def comment=(comment)
|
759
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
760
|
-
raise TypeError unless comment.is_a?(String)
|
761
|
-
|
762
|
-
if comment.length > MAX_COMMENT_LENGTH
|
763
|
-
raise Error.new(_("Comment has exceeded maximum allowed length %{max}") % { max: MAX_COMMENT_LENGTH })
|
764
|
-
end
|
765
|
-
|
766
|
-
@pITask.SetComment(wide_string(comment))
|
767
|
-
comment
|
768
|
-
end
|
769
|
-
|
770
|
-
# Returns the name of the user who created the task.
|
771
|
-
#
|
772
|
-
def creator
|
773
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
774
|
-
|
775
|
-
creator = nil
|
776
|
-
|
777
|
-
FFI::MemoryPointer.new(:pointer) do |ptr|
|
778
|
-
@pITask.GetCreator(ptr)
|
779
|
-
|
780
|
-
ptr.read_com_memory_pointer do |str_ptr|
|
781
|
-
creator = str_ptr.read_arbitrary_wide_string_up_to(MAX_ACCOUNT_LENGTH) if ! str_ptr.null?
|
782
|
-
end
|
783
|
-
end
|
784
|
-
|
785
|
-
creator
|
786
|
-
end
|
787
|
-
|
788
|
-
# Sets the creator for the task.
|
789
|
-
#
|
790
|
-
def creator=(creator)
|
791
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
792
|
-
raise TypeError unless creator.is_a?(String)
|
793
|
-
|
794
|
-
if creator.length > MAX_ACCOUNT_LENGTH
|
795
|
-
raise Error.new(_("Creator has exceeded maximum allowed length %{max}") % { max: MAX_ACCOUNT_LENGTH })
|
796
|
-
end
|
797
|
-
|
798
|
-
|
799
|
-
@pITask.SetCreator(wide_string(creator))
|
800
|
-
creator
|
801
|
-
end
|
802
|
-
|
803
|
-
# Returns a Time object that indicates the next time the task will run.
|
804
|
-
#
|
805
|
-
def next_run_time
|
806
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
807
|
-
|
808
|
-
time = nil
|
809
|
-
|
810
|
-
FFI::MemoryPointer.new(WIN32::SYSTEMTIME.size) do |ptr|
|
811
|
-
@pITask.GetNextRunTime(ptr)
|
812
|
-
time = WIN32::SYSTEMTIME.new(ptr).to_local_time
|
813
|
-
end
|
814
|
-
|
815
|
-
time
|
816
|
-
end
|
817
|
-
|
818
|
-
# Returns a Time object indicating the most recent time the task ran or
|
819
|
-
# nil if the task has never run.
|
820
|
-
#
|
821
|
-
def most_recent_run_time
|
822
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
823
|
-
|
824
|
-
time = nil
|
825
|
-
|
826
|
-
begin
|
827
|
-
FFI::MemoryPointer.new(WIN32::SYSTEMTIME.size) do |ptr|
|
828
|
-
@pITask.GetMostRecentRunTime(ptr)
|
829
|
-
time = WIN32::SYSTEMTIME.new(ptr).to_local_time
|
830
|
-
end
|
831
|
-
rescue Puppet::Util::Windows::Error => e
|
832
|
-
raise e unless e.code == SCHED_S_TASK_HAS_NOT_RUN
|
833
|
-
end
|
834
|
-
|
835
|
-
time
|
836
|
-
end
|
837
|
-
|
838
|
-
# Returns the maximum length of time, in milliseconds, that the task
|
839
|
-
# will run before terminating.
|
840
|
-
#
|
841
|
-
def max_run_time
|
842
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
843
|
-
|
844
|
-
max_run_time = nil
|
845
|
-
|
846
|
-
FFI::MemoryPointer.new(:dword, 1) do |ptr|
|
847
|
-
@pITask.GetMaxRunTime(ptr)
|
848
|
-
max_run_time = ptr.read_dword
|
849
|
-
end
|
850
|
-
|
851
|
-
max_run_time
|
852
|
-
end
|
853
|
-
|
854
|
-
# Sets the maximum length of time, in milliseconds, that the task can run
|
855
|
-
# before terminating. Returns the value you specified if successful.
|
856
|
-
#
|
857
|
-
def max_run_time=(max_run_time)
|
858
|
-
raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
|
859
|
-
raise TypeError unless max_run_time.is_a?(Numeric)
|
860
|
-
|
861
|
-
@pITask.SetMaxRunTime(max_run_time)
|
862
|
-
max_run_time
|
863
|
-
end
|
864
|
-
|
865
|
-
# Returns whether or not the scheduled task exists.
|
866
|
-
def exists?(job_name)
|
867
|
-
# task name comparison is case insensitive
|
868
|
-
tasks.any? { |name| name.casecmp(job_name + '.job') == 0 }
|
869
|
-
end
|
870
|
-
|
871
|
-
private
|
872
|
-
|
873
|
-
# :stopdoc:
|
874
|
-
|
875
|
-
# Used for the new_work_item method
|
876
|
-
ValidTriggerKeys = [
|
877
|
-
'end_day',
|
878
|
-
'end_month',
|
879
|
-
'end_year',
|
880
|
-
'flags',
|
881
|
-
'minutes_duration',
|
882
|
-
'minutes_interval',
|
883
|
-
'random_minutes_interval',
|
884
|
-
'start_day',
|
885
|
-
'start_hour',
|
886
|
-
'start_minute',
|
887
|
-
'start_month',
|
888
|
-
'start_year',
|
889
|
-
'trigger_type',
|
890
|
-
'type'
|
891
|
-
]
|
892
|
-
|
893
|
-
ValidTypeKeys = [
|
894
|
-
'days_interval',
|
895
|
-
'weeks_interval',
|
896
|
-
'days_of_week',
|
897
|
-
'months',
|
898
|
-
'days',
|
899
|
-
'weeks'
|
900
|
-
]
|
901
|
-
|
902
|
-
# Private method that validates keys, and converts all keys to lowercase
|
903
|
-
# strings.
|
904
|
-
#
|
905
|
-
def transform_and_validate(hash)
|
906
|
-
new_hash = {}
|
907
|
-
|
908
|
-
hash.each{ |key, value|
|
909
|
-
key = key.to_s.downcase
|
910
|
-
if key == 'type'
|
911
|
-
new_type_hash = {}
|
912
|
-
raise ArgumentError unless value.is_a?(Hash)
|
913
|
-
value.each{ |subkey, subvalue|
|
914
|
-
subkey = subkey.to_s.downcase
|
915
|
-
if ValidTypeKeys.include?(subkey)
|
916
|
-
new_type_hash[subkey] = subvalue
|
917
|
-
else
|
918
|
-
raise ArgumentError, _("Invalid type key '%{key}'") % { key: subkey }
|
919
|
-
end
|
920
|
-
}
|
921
|
-
new_hash[key] = new_type_hash
|
922
|
-
else
|
923
|
-
if ValidTriggerKeys.include?(key)
|
924
|
-
new_hash[key] = value
|
925
|
-
else
|
926
|
-
raise ArgumentError, _("Invalid key '%{key}'") % { key: key }
|
927
|
-
end
|
928
|
-
end
|
929
|
-
}
|
930
|
-
|
931
|
-
new_hash
|
932
|
-
end
|
933
|
-
|
934
|
-
def reset_current_task
|
935
|
-
# Ensure that COM reference is decremented properly
|
936
|
-
@pITask.Release if @pITask && ! @pITask.null?
|
937
|
-
@pITask = nil
|
938
|
-
@account_information_set = false
|
939
|
-
end
|
940
|
-
|
941
|
-
def populate_trigger(task_trigger, trigger)
|
942
|
-
raise TypeError unless task_trigger.is_a?(COM::TaskTrigger)
|
943
|
-
trigger = transform_and_validate(trigger)
|
944
|
-
|
945
|
-
FFI::MemoryPointer.new(COM::TASK_TRIGGER.size) do |trigger_ptr|
|
946
|
-
FFI::MemoryPointer.new(COM::TRIGGER_TYPE_UNION.size) do |trigger_type_union_ptr|
|
947
|
-
trigger_type_union = COM::TRIGGER_TYPE_UNION.new(trigger_type_union_ptr)
|
948
|
-
|
949
|
-
tmp = trigger['type'].is_a?(Hash) ? trigger['type'] : nil
|
950
|
-
case trigger['trigger_type']
|
951
|
-
when :TASK_TIME_TRIGGER_DAILY
|
952
|
-
if tmp && tmp['days_interval']
|
953
|
-
trigger_type_union[:Daily][:DaysInterval] = tmp['days_interval']
|
954
|
-
end
|
955
|
-
when :TASK_TIME_TRIGGER_WEEKLY
|
956
|
-
if tmp && tmp['weeks_interval'] && tmp['days_of_week']
|
957
|
-
trigger_type_union[:Weekly][:WeeksInterval] = tmp['weeks_interval']
|
958
|
-
trigger_type_union[:Weekly][:rgfDaysOfTheWeek] = tmp['days_of_week']
|
959
|
-
end
|
960
|
-
when :TASK_TIME_TRIGGER_MONTHLYDATE
|
961
|
-
if tmp && tmp['months'] && tmp['days']
|
962
|
-
trigger_type_union[:MonthlyDate][:rgfDays] = tmp['days']
|
963
|
-
trigger_type_union[:MonthlyDate][:rgfMonths] = tmp['months']
|
964
|
-
end
|
965
|
-
when :TASK_TIME_TRIGGER_MONTHLYDOW
|
966
|
-
if tmp && tmp['weeks'] && tmp['days_of_week'] && tmp['months']
|
967
|
-
trigger_type_union[:MonthlyDOW][:wWhichWeek] = tmp['weeks']
|
968
|
-
trigger_type_union[:MonthlyDOW][:rgfDaysOfTheWeek] = tmp['days_of_week']
|
969
|
-
trigger_type_union[:MonthlyDOW][:rgfMonths] = tmp['months']
|
970
|
-
end
|
971
|
-
when :TASK_TIME_TRIGGER_ONCE
|
972
|
-
# Do nothing. The Type member of the TASK_TRIGGER struct is ignored.
|
973
|
-
else
|
974
|
-
raise Error.new(_("Unknown trigger type %{type}") % { type: trigger['trigger_type'] })
|
975
|
-
end
|
976
|
-
|
977
|
-
trigger_struct = COM::TASK_TRIGGER.new(trigger_ptr)
|
978
|
-
trigger_struct[:cbTriggerSize] = COM::TASK_TRIGGER.size
|
979
|
-
now = Time.now
|
980
|
-
trigger_struct[:wBeginYear] = trigger['start_year'] || now.year
|
981
|
-
trigger_struct[:wBeginMonth] = trigger['start_month'] || now.month
|
982
|
-
trigger_struct[:wBeginDay] = trigger['start_day'] || now.day
|
983
|
-
trigger_struct[:wEndYear] = trigger['end_year'] || 0
|
984
|
-
trigger_struct[:wEndMonth] = trigger['end_month'] || 0
|
985
|
-
trigger_struct[:wEndDay] = trigger['end_day'] || 0
|
986
|
-
trigger_struct[:wStartHour] = trigger['start_hour'] || 0
|
987
|
-
trigger_struct[:wStartMinute] = trigger['start_minute'] || 0
|
988
|
-
trigger_struct[:MinutesDuration] = trigger['minutes_duration'] || 0
|
989
|
-
trigger_struct[:MinutesInterval] = trigger['minutes_interval'] || 0
|
990
|
-
trigger_struct[:rgFlags] = trigger['flags'] || 0
|
991
|
-
trigger_struct[:TriggerType] = trigger['trigger_type'] || :TASK_TIME_TRIGGER_ONCE
|
992
|
-
trigger_struct[:Type] = trigger_type_union
|
993
|
-
trigger_struct[:wRandomMinutesInterval] = trigger['random_minutes_interval'] || 0
|
994
|
-
|
995
|
-
task_trigger.SetTrigger(trigger_struct)
|
996
|
-
end
|
997
|
-
end
|
998
|
-
end
|
999
|
-
|
1000
|
-
def populate_hash_from_trigger(task_trigger)
|
1001
|
-
raise TypeError unless task_trigger.is_a?(COM::TASK_TRIGGER)
|
1002
|
-
|
1003
|
-
trigger = {
|
1004
|
-
'start_year' => task_trigger[:wBeginYear],
|
1005
|
-
'start_month' => task_trigger[:wBeginMonth],
|
1006
|
-
'start_day' => task_trigger[:wBeginDay],
|
1007
|
-
'end_year' => task_trigger[:wEndYear],
|
1008
|
-
'end_month' => task_trigger[:wEndMonth],
|
1009
|
-
'end_day' => task_trigger[:wEndDay],
|
1010
|
-
'start_hour' => task_trigger[:wStartHour],
|
1011
|
-
'start_minute' => task_trigger[:wStartMinute],
|
1012
|
-
'minutes_duration' => task_trigger[:MinutesDuration],
|
1013
|
-
'minutes_interval' => task_trigger[:MinutesInterval],
|
1014
|
-
'flags' => task_trigger[:rgFlags],
|
1015
|
-
'trigger_type' => task_trigger[:TriggerType],
|
1016
|
-
'random_minutes_interval' => task_trigger[:wRandomMinutesInterval]
|
1017
|
-
}
|
1018
|
-
|
1019
|
-
case task_trigger[:TriggerType]
|
1020
|
-
when :TASK_TIME_TRIGGER_DAILY
|
1021
|
-
trigger['type'] = { 'days_interval' => task_trigger[:Type][:Daily][:DaysInterval] }
|
1022
|
-
when :TASK_TIME_TRIGGER_WEEKLY
|
1023
|
-
trigger['type'] = {
|
1024
|
-
'weeks_interval' => task_trigger[:Type][:Weekly][:WeeksInterval],
|
1025
|
-
'days_of_week' => task_trigger[:Type][:Weekly][:rgfDaysOfTheWeek]
|
1026
|
-
}
|
1027
|
-
when :TASK_TIME_TRIGGER_MONTHLYDATE
|
1028
|
-
trigger['type'] = {
|
1029
|
-
'days' => task_trigger[:Type][:MonthlyDate][:rgfDays],
|
1030
|
-
'months' => task_trigger[:Type][:MonthlyDate][:rgfMonths]
|
1031
|
-
}
|
1032
|
-
when :TASK_TIME_TRIGGER_MONTHLYDOW
|
1033
|
-
trigger['type'] = {
|
1034
|
-
'weeks' => task_trigger[:Type][:MonthlyDOW][:wWhichWeek],
|
1035
|
-
'days_of_week' => task_trigger[:Type][:MonthlyDOW][:rgfDaysOfTheWeek],
|
1036
|
-
'months' => task_trigger[:Type][:MonthlyDOW][:rgfMonths]
|
1037
|
-
}
|
1038
|
-
when :TASK_TIME_TRIGGER_ONCE
|
1039
|
-
trigger['type'] = { 'once' => nil }
|
1040
|
-
else
|
1041
|
-
raise Error.new(_("Unknown trigger type %{type}") % { type: task_trigger[:TriggerType] })
|
1042
|
-
end
|
1043
|
-
|
1044
|
-
trigger
|
1045
|
-
end
|
1046
|
-
|
1047
|
-
module COM
|
1048
|
-
extend FFI::Library
|
1049
|
-
|
1050
|
-
com = Puppet::Util::Windows::COM
|
1051
|
-
|
1052
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa381811(v=vs.85).aspx
|
1053
|
-
ITaskScheduler = com::Interface[com::IUnknown,
|
1054
|
-
FFI::WIN32::GUID['148BD527-A2AB-11CE-B11F-00AA00530503'],
|
1055
|
-
|
1056
|
-
SetTargetComputer: [[:lpcwstr], :hresult],
|
1057
|
-
# LPWSTR *
|
1058
|
-
GetTargetComputer: [[:pointer], :hresult],
|
1059
|
-
# IEnumWorkItems **
|
1060
|
-
Enum: [[:pointer], :hresult],
|
1061
|
-
# LPCWSTR, REFIID, IUnknown **
|
1062
|
-
Activate: [[:lpcwstr, :pointer, :pointer], :hresult],
|
1063
|
-
Delete: [[:lpcwstr], :hresult],
|
1064
|
-
# LPCWSTR, REFCLSID, REFIID, IUnknown **
|
1065
|
-
NewWorkItem: [[:lpcwstr, :pointer, :pointer, :pointer], :hresult],
|
1066
|
-
# LPCWSTR, IScheduledWorkItem *
|
1067
|
-
AddWorkItem: [[:lpcwstr, :pointer], :hresult],
|
1068
|
-
# LPCWSTR, REFIID
|
1069
|
-
IsOfType: [[:lpcwstr, :pointer], :hresult]
|
1070
|
-
]
|
1071
|
-
|
1072
|
-
TaskScheduler = com::Factory[ITaskScheduler,
|
1073
|
-
FFI::WIN32::GUID['148BD52A-A2AB-11CE-B11F-00AA00530503']]
|
1074
|
-
|
1075
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa380706(v=vs.85).aspx
|
1076
|
-
IEnumWorkItems = com::Interface[com::IUnknown,
|
1077
|
-
FFI::WIN32::GUID['148BD528-A2AB-11CE-B11F-00AA00530503'],
|
1078
|
-
|
1079
|
-
# ULONG, LPWSTR **, ULONG *
|
1080
|
-
Next: [[:win32_ulong, :pointer, :pointer], :hresult],
|
1081
|
-
Skip: [[:win32_ulong], :hresult],
|
1082
|
-
Reset: [[], :hresult],
|
1083
|
-
# IEnumWorkItems ** ppEnumWorkItems
|
1084
|
-
Clone: [[:pointer], :hresult]
|
1085
|
-
]
|
1086
|
-
|
1087
|
-
EnumWorkItems = com::Instance[IEnumWorkItems]
|
1088
|
-
|
1089
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa381216(v=vs.85).aspx
|
1090
|
-
IScheduledWorkItem = com::Interface[com::IUnknown,
|
1091
|
-
FFI::WIN32::GUID['a6b952f0-a4b1-11d0-997d-00aa006887ec'],
|
1092
|
-
|
1093
|
-
# WORD *, ITaskTrigger **
|
1094
|
-
CreateTrigger: [[:pointer, :pointer], :hresult],
|
1095
|
-
DeleteTrigger: [[:word], :hresult],
|
1096
|
-
# WORD *
|
1097
|
-
GetTriggerCount: [[:pointer], :hresult],
|
1098
|
-
# WORD, ITaskTrigger **
|
1099
|
-
GetTrigger: [[:word, :pointer], :hresult],
|
1100
|
-
# WORD, LPWSTR *
|
1101
|
-
GetTriggerString: [[:word, :pointer], :hresult],
|
1102
|
-
# LPSYSTEMTIME, LPSYSTEMTIME, WORD *, LPSYSTEMTIME *
|
1103
|
-
GetRunTimes: [[:pointer, :pointer, :pointer, :pointer], :hresult],
|
1104
|
-
# SYSTEMTIME *
|
1105
|
-
GetNextRunTime: [[:pointer], :hresult],
|
1106
|
-
SetIdleWait: [[:word, :word], :hresult],
|
1107
|
-
# WORD *, WORD *
|
1108
|
-
GetIdleWait: [[:pointer, :pointer], :hresult],
|
1109
|
-
Run: [[], :hresult],
|
1110
|
-
Terminate: [[], :hresult],
|
1111
|
-
EditWorkItem: [[:hwnd, :dword], :hresult],
|
1112
|
-
# SYSTEMTIME *
|
1113
|
-
GetMostRecentRunTime: [[:pointer], :hresult],
|
1114
|
-
# HRESULT *
|
1115
|
-
GetStatus: [[:pointer], :hresult],
|
1116
|
-
GetExitCode: [[:pdword], :hresult],
|
1117
|
-
SetComment: [[:lpcwstr], :hresult],
|
1118
|
-
# LPWSTR *
|
1119
|
-
GetComment: [[:pointer], :hresult],
|
1120
|
-
SetCreator: [[:lpcwstr], :hresult],
|
1121
|
-
# LPWSTR *
|
1122
|
-
GetCreator: [[:pointer], :hresult],
|
1123
|
-
# WORD, BYTE[]
|
1124
|
-
SetWorkItemData: [[:word, :buffer_in], :hresult],
|
1125
|
-
# WORD *, BYTE **
|
1126
|
-
GetWorkItemData: [[:pointer, :pointer], :hresult],
|
1127
|
-
SetErrorRetryCount: [[:word], :hresult],
|
1128
|
-
# WORD *
|
1129
|
-
GetErrorRetryCount: [[:pointer], :hresult],
|
1130
|
-
SetErrorRetryInterval: [[:word], :hresult],
|
1131
|
-
# WORD *
|
1132
|
-
GetErrorRetryInterval: [[:pointer], :hresult],
|
1133
|
-
SetFlags: [[:dword], :hresult],
|
1134
|
-
# WORD *
|
1135
|
-
GetFlags: [[:pointer], :hresult],
|
1136
|
-
SetAccountInformation: [[:lpcwstr, :lpcwstr], :hresult],
|
1137
|
-
# LPWSTR *
|
1138
|
-
GetAccountInformation: [[:pointer], :hresult]
|
1139
|
-
]
|
1140
|
-
|
1141
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa381311(v=vs.85).aspx
|
1142
|
-
ITask = com::Interface[IScheduledWorkItem,
|
1143
|
-
FFI::WIN32::GUID['148BD524-A2AB-11CE-B11F-00AA00530503'],
|
1144
|
-
|
1145
|
-
SetApplicationName: [[:lpcwstr], :hresult],
|
1146
|
-
# LPWSTR *
|
1147
|
-
GetApplicationName: [[:pointer], :hresult],
|
1148
|
-
SetParameters: [[:lpcwstr], :hresult],
|
1149
|
-
# LPWSTR *
|
1150
|
-
GetParameters: [[:pointer], :hresult],
|
1151
|
-
SetWorkingDirectory: [[:lpcwstr], :hresult],
|
1152
|
-
# LPWSTR *
|
1153
|
-
GetWorkingDirectory: [[:pointer], :hresult],
|
1154
|
-
SetPriority: [[:dword], :hresult],
|
1155
|
-
# DWORD *
|
1156
|
-
GetPriority: [[:pointer], :hresult],
|
1157
|
-
SetTaskFlags: [[:dword], :hresult],
|
1158
|
-
# DWORD *
|
1159
|
-
GetTaskFlags: [[:pointer], :hresult],
|
1160
|
-
SetMaxRunTime: [[:dword], :hresult],
|
1161
|
-
# DWORD *
|
1162
|
-
GetMaxRunTime: [[:pointer], :hresult]
|
1163
|
-
]
|
1164
|
-
|
1165
|
-
Task = com::Instance[ITask]
|
1166
|
-
|
1167
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms688695(v=vs.85).aspx
|
1168
|
-
IPersist = com::Interface[com::IUnknown,
|
1169
|
-
FFI::WIN32::GUID['0000010c-0000-0000-c000-000000000046'],
|
1170
|
-
# CLSID *
|
1171
|
-
GetClassID: [[:pointer], :hresult]
|
1172
|
-
]
|
1173
|
-
|
1174
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms687223(v=vs.85).aspx
|
1175
|
-
IPersistFile = com::Interface[IPersist,
|
1176
|
-
FFI::WIN32::GUID['0000010b-0000-0000-C000-000000000046'],
|
1177
|
-
|
1178
|
-
IsDirty: [[], :hresult],
|
1179
|
-
Load: [[:lpcolestr, :dword], :hresult],
|
1180
|
-
Save: [[:lpcolestr, :win32_bool], :hresult],
|
1181
|
-
SaveCompleted: [[:lpcolestr], :hresult],
|
1182
|
-
# LPOLESTR *
|
1183
|
-
GetCurFile: [[:pointer], :hresult]
|
1184
|
-
]
|
1185
|
-
|
1186
|
-
PersistFile = com::Instance[IPersistFile]
|
1187
|
-
|
1188
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa381864(v=vs.85).aspx
|
1189
|
-
ITaskTrigger = com::Interface[com::IUnknown,
|
1190
|
-
FFI::WIN32::GUID['148BD52B-A2AB-11CE-B11F-00AA00530503'],
|
1191
|
-
|
1192
|
-
SetTrigger: [[:pointer], :hresult],
|
1193
|
-
GetTrigger: [[:pointer], :hresult],
|
1194
|
-
GetTriggerString: [[:pointer], :hresult]
|
1195
|
-
]
|
1196
|
-
|
1197
|
-
TaskTrigger = com::Instance[ITaskTrigger]
|
1198
|
-
|
1199
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa383620(v=vs.85).aspx
|
1200
|
-
# The TASK_TRIGGER_TYPE field of the TASK_TRIGGER structure determines
|
1201
|
-
# which member of the TRIGGER_TYPE_UNION field to use.
|
1202
|
-
TASK_TRIGGER_TYPE = enum(
|
1203
|
-
:TASK_TIME_TRIGGER_ONCE, 0, # Ignore the Type field
|
1204
|
-
:TASK_TIME_TRIGGER_DAILY, 1,
|
1205
|
-
:TASK_TIME_TRIGGER_WEEKLY, 2,
|
1206
|
-
:TASK_TIME_TRIGGER_MONTHLYDATE, 3,
|
1207
|
-
:TASK_TIME_TRIGGER_MONTHLYDOW, 4,
|
1208
|
-
:TASK_EVENT_TRIGGER_ON_IDLE, 5, # Ignore the Type field
|
1209
|
-
:TASK_EVENT_TRIGGER_AT_SYSTEMSTART, 6, # Ignore the Type field
|
1210
|
-
:TASK_EVENT_TRIGGER_AT_LOGON, 7 # Ignore the Type field
|
1211
|
-
)
|
1212
|
-
|
1213
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa446857(v=vs.85).aspx
|
1214
|
-
class DAILY < FFI::Struct
|
1215
|
-
layout :DaysInterval, :word
|
1216
|
-
end
|
1217
|
-
|
1218
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa384014(v=vs.85).aspx
|
1219
|
-
class WEEKLY < FFI::Struct
|
1220
|
-
layout :WeeksInterval, :word,
|
1221
|
-
:rgfDaysOfTheWeek, :word
|
1222
|
-
end
|
1223
|
-
|
1224
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa381918(v=vs.85).aspx
|
1225
|
-
class MONTHLYDATE < FFI::Struct
|
1226
|
-
layout :rgfDays, :dword,
|
1227
|
-
:rgfMonths, :word
|
1228
|
-
end
|
1229
|
-
|
1230
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa381918(v=vs.85).aspx
|
1231
|
-
class MONTHLYDOW < FFI::Struct
|
1232
|
-
layout :wWhichWeek, :word,
|
1233
|
-
:rgfDaysOfTheWeek, :word,
|
1234
|
-
:rgfMonths, :word
|
1235
|
-
end
|
1236
|
-
|
1237
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa384002(v=vs.85).aspx
|
1238
|
-
class TRIGGER_TYPE_UNION < FFI::Union
|
1239
|
-
layout :Daily, DAILY,
|
1240
|
-
:Weekly, WEEKLY,
|
1241
|
-
:MonthlyDate, MONTHLYDATE,
|
1242
|
-
:MonthlyDOW, MONTHLYDOW
|
1243
|
-
end
|
1244
|
-
|
1245
|
-
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa383618(v=vs.85).aspx
|
1246
|
-
class TASK_TRIGGER < FFI::Struct
|
1247
|
-
layout :cbTriggerSize, :word, # Structure size.
|
1248
|
-
:Reserved1, :word, # Reserved. Must be zero.
|
1249
|
-
:wBeginYear, :word, # Trigger beginning date year.
|
1250
|
-
:wBeginMonth, :word, # Trigger beginning date month.
|
1251
|
-
:wBeginDay, :word, # Trigger beginning date day.
|
1252
|
-
:wEndYear, :word, # Optional trigger ending date year.
|
1253
|
-
:wEndMonth, :word, # Optional trigger ending date month.
|
1254
|
-
:wEndDay, :word, # Optional trigger ending date day.
|
1255
|
-
:wStartHour, :word, # Run bracket start time hour.
|
1256
|
-
:wStartMinute, :word, # Run bracket start time minute.
|
1257
|
-
:MinutesDuration, :dword, # Duration of run bracket.
|
1258
|
-
:MinutesInterval, :dword, # Run bracket repetition interval.
|
1259
|
-
:rgFlags, :dword, # Trigger flags.
|
1260
|
-
:TriggerType, TASK_TRIGGER_TYPE, # Trigger type.
|
1261
|
-
:Type, TRIGGER_TYPE_UNION, # Trigger data.
|
1262
|
-
:Reserved2, :word, # Reserved. Must be zero.
|
1263
|
-
:wRandomMinutesInterval, :word # Maximum number of random minutes after start time
|
1264
|
-
end
|
1265
|
-
end
|
1266
|
-
end
|
1267
|
-
end
|