win32-taskscheduler 0.1.0-x86-mswin32-60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +39 -0
- data/MANIFEST +11 -0
- data/README +62 -0
- data/ext/win32/taskscheduler.c +2036 -0
- data/lib/win32/taskscheduler.so +0 -0
- data/test/tc_taskscheduler.rb +494 -0
- metadata +62 -0
data/CHANGES
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
== 0.1.0 - 11-May-2008
|
2
|
+
* The TaskScheduler#save instance method now accepts an optional file name.
|
3
|
+
* Most of the TaskScheduler setter methods now return the value specified
|
4
|
+
instead of true.
|
5
|
+
* Removed the RUN_ONLY_IF_DOCKED and RUN_IF_CONNECTED_TO_INTERNET constants.
|
6
|
+
The MSDN docs say that they are unused.
|
7
|
+
* Added more documentation. Much more rdoc friendly now.
|
8
|
+
* Added many more tests.
|
9
|
+
* Better type handling for bad arguments.
|
10
|
+
* Added a Rakefile with tasks for building, installation and testing.
|
11
|
+
* Added a gemspec.
|
12
|
+
* Inlined the rdoc documentation.
|
13
|
+
* Internal project reorganization and code cleanup.
|
14
|
+
|
15
|
+
== 0.0.3 - 1-Mar-2005
|
16
|
+
* Bug fix for the bitFieldToHumanDays() internal function.
|
17
|
+
* Moved the 'examples' directory to the toplevel directory.
|
18
|
+
* Made the CHANGES and README files rdoc friendly.
|
19
|
+
* Minor updates to taskscheduler.h.
|
20
|
+
|
21
|
+
== 0.0.2 - 04-Aug-2004
|
22
|
+
* Now uses the newer allocation framework and replaced all instances of the
|
23
|
+
deprecated STR2CSTR() function with StringValuePtr(). This means that, as
|
24
|
+
of this release, Ruby 1.8.0 or later is required.
|
25
|
+
* Modified the constructor to accept arguments. This is just some sugar for
|
26
|
+
creating a new task item in one call instead of two.
|
27
|
+
* The argument to trigger= now must be a hash. The same goes for the 'type'
|
28
|
+
sub-hash.
|
29
|
+
* Added the add_trigger() method. Actually, the C code for this method was
|
30
|
+
already in place, I simply forgot to create a corresponding Ruby method
|
31
|
+
for it.
|
32
|
+
* Removed the create_trigger() method. This was really nothing more than an
|
33
|
+
alias for trigger=(). I got confused somehow.
|
34
|
+
* Test suite modified and many more tests added.
|
35
|
+
* Documentation updates, including docs for a couple of methods that I had
|
36
|
+
accidentally omitted previously.
|
37
|
+
|
38
|
+
== 0.0.1 - 24-Apr-2004
|
39
|
+
* Initial release
|
data/MANIFEST
ADDED
data/README
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
= Description
|
2
|
+
The win32-taskscheduler library is a Ruby interface to the MS Windows Task
|
3
|
+
Scheduler. It is analogous to the Unix cron daemon.
|
4
|
+
|
5
|
+
= Synopsis
|
6
|
+
require 'win32/taskscheduler'
|
7
|
+
include Win32
|
8
|
+
|
9
|
+
t = TaskScheduler.new
|
10
|
+
|
11
|
+
trigger = {
|
12
|
+
:start_year => 2014,
|
13
|
+
:start_month => 4,
|
14
|
+
:start_day => 25,
|
15
|
+
:start_hour => 23,
|
16
|
+
:start_minute => 5,
|
17
|
+
:trigger_type => TaskScheduler::MONTHLY_DOW,
|
18
|
+
:type => {
|
19
|
+
:weeks => TaskScheduler::FIRST | TaskScheduler::LAST,
|
20
|
+
:days_of_week => TaskScheduler::MONDAY | TaskScheduler::FRIDAY,
|
21
|
+
:months => TaskScheduler::APRIL | TaskScheduler::MAY
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
t.new_work_item('foo', trigger)
|
26
|
+
t.application_name = 'notepad.exe'
|
27
|
+
t.save
|
28
|
+
|
29
|
+
= Prerequisites
|
30
|
+
Ruby 1.8.2 or later. Building from source requires VC++ 6.0 or later.
|
31
|
+
|
32
|
+
= Installation
|
33
|
+
rake install (non-gem) OR rake install_gem (gem)
|
34
|
+
|
35
|
+
For most of you 'gem install win32-taskscheduler' will work.
|
36
|
+
|
37
|
+
= Documentation
|
38
|
+
If you installed this library as a gem then the documentation was built for
|
39
|
+
you and can be viewed if your gem server is running.
|
40
|
+
|
41
|
+
Otherwise, you can look at the doc/taskscheduler.txt file which should have
|
42
|
+
everything you need.
|
43
|
+
|
44
|
+
= Acknowledgements
|
45
|
+
This library was modeled to some degree on the Win32::TaskScheduler Perl
|
46
|
+
module by Umberto Nicoletti. However, there are some differences. Please see
|
47
|
+
the documentation for details.
|
48
|
+
|
49
|
+
= On using OLE + WMI + Win32_ScheduledJob
|
50
|
+
I will probably include a pure Ruby version of this library at some point,
|
51
|
+
and you can find what I have so far in CVS under lib/win32. Note, however,
|
52
|
+
that there are some significant differences in behavior between the C
|
53
|
+
library and WMI, along with limitations regarding modification to existing
|
54
|
+
tasks.
|
55
|
+
|
56
|
+
You can find a list of differences here: http://tinyurl.com/2l3yau
|
57
|
+
|
58
|
+
= Developer's Notes
|
59
|
+
The CoInitialize() function is used internally instead of CoInitializeEx()
|
60
|
+
function intentionally. The CoInitialize() function merely calls the
|
61
|
+
CoInitializeEx() function with NULL and COINIT_APARTMENTTHREADED arguments,
|
62
|
+
which is what we would do in any case.
|
@@ -0,0 +1,2036 @@
|
|
1
|
+
/* taskscheduler.c */
|
2
|
+
#include "ruby.h"
|
3
|
+
#include <windows.h>
|
4
|
+
#include <initguid.h>
|
5
|
+
#include <ole2.h>
|
6
|
+
#include <mstask.h>
|
7
|
+
#include <msterr.h>
|
8
|
+
#include <objidl.h>
|
9
|
+
#include <wchar.h>
|
10
|
+
#include <stdio.h>
|
11
|
+
#include <tchar.h>
|
12
|
+
#include <comutil.h>
|
13
|
+
#include "taskscheduler.h"
|
14
|
+
|
15
|
+
static TCHAR error[ERROR_BUFFER];
|
16
|
+
|
17
|
+
static VALUE ts_allocate(VALUE klass){
|
18
|
+
TSStruct* ptr = (TSStruct*)malloc(sizeof(TSStruct));
|
19
|
+
return Data_Wrap_Struct(klass, 0, ts_free, ptr);
|
20
|
+
}
|
21
|
+
|
22
|
+
/*
|
23
|
+
* call-seq: TaskScheduler.new(work_item, host=nil)
|
24
|
+
*
|
25
|
+
* Returns a new TaskScheduler object. If a work_item (and possibly
|
26
|
+
* the trigger) are passed as arguments then a new work item is created and
|
27
|
+
* associated with that trigger, although you can still activate other tasks
|
28
|
+
* with the same handle.
|
29
|
+
*
|
30
|
+
* This is really just a bit of convenience. Passing arguments to the
|
31
|
+
* constructor is the same as calling new + new_work_item.
|
32
|
+
*/
|
33
|
+
static VALUE ts_init(int argc, VALUE *argv, VALUE self)
|
34
|
+
{
|
35
|
+
ITaskScheduler *pITS;
|
36
|
+
HRESULT hr = S_OK;
|
37
|
+
TSStruct* ptr;
|
38
|
+
VALUE v_taskname, v_trigger;
|
39
|
+
|
40
|
+
Data_Get_Struct(self,TSStruct,ptr);
|
41
|
+
ptr->pITS = NULL;
|
42
|
+
ptr->pITask = NULL;
|
43
|
+
|
44
|
+
rb_scan_args(argc, argv, "02", &v_taskname, &v_trigger);
|
45
|
+
|
46
|
+
hr = CoInitialize(NULL);
|
47
|
+
|
48
|
+
if(SUCCEEDED(hr)){
|
49
|
+
hr = CoCreateInstance(
|
50
|
+
CLSID_CTaskScheduler,
|
51
|
+
NULL,
|
52
|
+
CLSCTX_INPROC_SERVER,
|
53
|
+
IID_ITaskScheduler,
|
54
|
+
(void **) &pITS
|
55
|
+
);
|
56
|
+
|
57
|
+
if(FAILED(hr))
|
58
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
59
|
+
}
|
60
|
+
else{
|
61
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
62
|
+
}
|
63
|
+
|
64
|
+
ptr->pITS = pITS;
|
65
|
+
ptr->pITask = NULL;
|
66
|
+
|
67
|
+
if(Qnil != v_taskname){
|
68
|
+
if(Qnil != v_trigger){
|
69
|
+
Check_Type(v_trigger,T_HASH);
|
70
|
+
ts_new_work_item(self,v_taskname,v_trigger);
|
71
|
+
}
|
72
|
+
else{
|
73
|
+
ts_new_work_item(self,v_taskname,Qnil);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
return self;
|
78
|
+
}
|
79
|
+
|
80
|
+
/*
|
81
|
+
* Returns an array of scheduled tasks.
|
82
|
+
*/
|
83
|
+
static VALUE ts_enum(VALUE self)
|
84
|
+
{
|
85
|
+
TSStruct* ptr;
|
86
|
+
HRESULT hr;
|
87
|
+
IEnumWorkItems *pIEnum;
|
88
|
+
LPWSTR *lpwszNames;
|
89
|
+
VALUE v_enum;
|
90
|
+
TCHAR dest[NAME_MAX];
|
91
|
+
DWORD dwFetchedTasks = 0;
|
92
|
+
|
93
|
+
Data_Get_Struct(self,TSStruct,ptr);
|
94
|
+
|
95
|
+
if(ptr->pITS == NULL)
|
96
|
+
rb_raise(cTSError, "fatal error: null pointer(ts_enum)");
|
97
|
+
|
98
|
+
hr = ptr->pITS->Enum(&pIEnum);
|
99
|
+
|
100
|
+
if(FAILED(hr))
|
101
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
102
|
+
|
103
|
+
v_enum = rb_ary_new();
|
104
|
+
|
105
|
+
while(SUCCEEDED(pIEnum->Next(TASKS_TO_RETRIEVE,
|
106
|
+
&lpwszNames,
|
107
|
+
&dwFetchedTasks))
|
108
|
+
&& (dwFetchedTasks != 0)
|
109
|
+
)
|
110
|
+
{
|
111
|
+
while(dwFetchedTasks){
|
112
|
+
WideCharToMultiByte(
|
113
|
+
CP_ACP,
|
114
|
+
0,
|
115
|
+
lpwszNames[--dwFetchedTasks],
|
116
|
+
-1,
|
117
|
+
dest,
|
118
|
+
NAME_MAX,
|
119
|
+
NULL,
|
120
|
+
NULL
|
121
|
+
);
|
122
|
+
|
123
|
+
rb_ary_push(v_enum, rb_str_new2(dest));
|
124
|
+
CoTaskMemFree(lpwszNames[dwFetchedTasks]);
|
125
|
+
}
|
126
|
+
CoTaskMemFree(lpwszNames);
|
127
|
+
}
|
128
|
+
|
129
|
+
pIEnum->Release();
|
130
|
+
|
131
|
+
return v_enum;
|
132
|
+
}
|
133
|
+
|
134
|
+
/*
|
135
|
+
* call-seq:
|
136
|
+
* TaskScheduler#activate(task)
|
137
|
+
*
|
138
|
+
* Activates the given +task+.
|
139
|
+
*/
|
140
|
+
static VALUE ts_activate(VALUE self, VALUE v_task){
|
141
|
+
TSStruct* ptr;
|
142
|
+
HRESULT hr;
|
143
|
+
wchar_t cwszTaskName[NAME_MAX];
|
144
|
+
|
145
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
146
|
+
|
147
|
+
if(ptr->pITS == NULL)
|
148
|
+
rb_raise(cTSError, "fatal error: null pointer (ts_activate)");
|
149
|
+
|
150
|
+
StringValue(v_task);
|
151
|
+
|
152
|
+
MultiByteToWideChar(
|
153
|
+
CP_ACP,
|
154
|
+
0,
|
155
|
+
StringValuePtr(v_task),
|
156
|
+
RSTRING(v_task)->len+1,
|
157
|
+
cwszTaskName,
|
158
|
+
NAME_MAX
|
159
|
+
);
|
160
|
+
|
161
|
+
hr = ptr->pITS->Activate(cwszTaskName,IID_ITask,
|
162
|
+
(IUnknown**) &(ptr->pITask));
|
163
|
+
|
164
|
+
if(FAILED(hr))
|
165
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
166
|
+
|
167
|
+
return self;
|
168
|
+
}
|
169
|
+
|
170
|
+
/*
|
171
|
+
* Deletes the specified +task+.
|
172
|
+
*/
|
173
|
+
static VALUE ts_delete(VALUE self, VALUE v_task)
|
174
|
+
{
|
175
|
+
TSStruct* ptr;
|
176
|
+
HRESULT hr;
|
177
|
+
wchar_t cwszTaskName[NAME_MAX];
|
178
|
+
|
179
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
180
|
+
StringValue(v_task);
|
181
|
+
|
182
|
+
if(ptr->pITS == NULL)
|
183
|
+
rb_raise(cTSError, "fatal error: null pointer (ts_delete)");
|
184
|
+
|
185
|
+
MultiByteToWideChar(
|
186
|
+
CP_ACP,
|
187
|
+
0,
|
188
|
+
StringValuePtr(v_task),
|
189
|
+
RSTRING(v_task)->len + 1,
|
190
|
+
cwszTaskName,
|
191
|
+
NAME_MAX
|
192
|
+
);
|
193
|
+
|
194
|
+
hr = ptr->pITS->Delete(cwszTaskName);
|
195
|
+
|
196
|
+
if(FAILED(hr))
|
197
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
198
|
+
|
199
|
+
return self;
|
200
|
+
}
|
201
|
+
|
202
|
+
/*
|
203
|
+
* Executes the current task.
|
204
|
+
*/
|
205
|
+
static VALUE ts_run(VALUE self)
|
206
|
+
{
|
207
|
+
TSStruct* ptr;
|
208
|
+
HRESULT hr;
|
209
|
+
|
210
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
211
|
+
|
212
|
+
if(ptr->pITask == NULL)
|
213
|
+
rb_raise(cTSError, "fatal error: null pointer (ts_run)");
|
214
|
+
|
215
|
+
hr = ptr->pITask->Run();
|
216
|
+
|
217
|
+
if(FAILED(hr))
|
218
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
219
|
+
|
220
|
+
return self;
|
221
|
+
}
|
222
|
+
|
223
|
+
/*
|
224
|
+
* call-seq:
|
225
|
+
* TaskScheduler#save(file=nil)
|
226
|
+
*
|
227
|
+
* Saves the current task. Tasks must be saved before they can be activated.
|
228
|
+
* The .job file itself is typically stored in the C:\WINDOWS\Tasks folder.
|
229
|
+
*
|
230
|
+
* If +file+ (an absolute path) is specified then the job is saved to that
|
231
|
+
* file instead. A '.job' extension is recommended but not enforced.
|
232
|
+
*
|
233
|
+
* Note that calling TaskScheduler#save also resets the TaskScheduler object
|
234
|
+
* so that there is no currently active task.
|
235
|
+
*/
|
236
|
+
static VALUE ts_save(int argc, VALUE* argv, VALUE self)
|
237
|
+
{
|
238
|
+
TSStruct* ptr;
|
239
|
+
HRESULT hr;
|
240
|
+
IPersistFile *pIPersistFile;
|
241
|
+
LPOLESTR ppszFileName = NULL;
|
242
|
+
VALUE v_bool = Qfalse;
|
243
|
+
VALUE v_file = Qnil;
|
244
|
+
|
245
|
+
rb_scan_args(argc, argv, "01", &v_file);
|
246
|
+
|
247
|
+
if(!NIL_P(v_file))
|
248
|
+
ppszFileName = _bstr_t(StringValuePtr(v_file));
|
249
|
+
|
250
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
251
|
+
|
252
|
+
if(ptr->pITask == NULL)
|
253
|
+
rb_raise(cTSError, "fatal error: null pointer (ts_save)");
|
254
|
+
|
255
|
+
hr = ptr->pITask->QueryInterface(IID_IPersistFile,
|
256
|
+
(void **)&pIPersistFile);
|
257
|
+
|
258
|
+
if(FAILED(hr))
|
259
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
260
|
+
|
261
|
+
hr = pIPersistFile->Save(ppszFileName, TRUE);
|
262
|
+
|
263
|
+
if(FAILED(hr)){
|
264
|
+
strcpy(error, ErrorString(GetLastError()));
|
265
|
+
pIPersistFile->Release();
|
266
|
+
rb_raise(cTSError, error);
|
267
|
+
}
|
268
|
+
|
269
|
+
pIPersistFile->Release();
|
270
|
+
|
271
|
+
// Call CoInitialize to initialize the COM library and then
|
272
|
+
// CoCreateInstance to get the Task Scheduler object.
|
273
|
+
// - Added by phasis68
|
274
|
+
CoUninitialize();
|
275
|
+
hr = CoInitialize(NULL);
|
276
|
+
|
277
|
+
if(SUCCEEDED(hr)){
|
278
|
+
hr = CoCreateInstance(
|
279
|
+
CLSID_CTaskScheduler,
|
280
|
+
NULL,
|
281
|
+
CLSCTX_INPROC_SERVER,
|
282
|
+
IID_ITaskScheduler,
|
283
|
+
(void **) &(ptr->pITS)
|
284
|
+
);
|
285
|
+
|
286
|
+
if(FAILED(hr)){
|
287
|
+
CoUninitialize();
|
288
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
289
|
+
}
|
290
|
+
}
|
291
|
+
else{
|
292
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
293
|
+
}
|
294
|
+
|
295
|
+
ptr->pITask->Release();
|
296
|
+
ptr->pITask = NULL;
|
297
|
+
|
298
|
+
return self;
|
299
|
+
}
|
300
|
+
|
301
|
+
/*
|
302
|
+
* Terminate the current task.
|
303
|
+
*/
|
304
|
+
static VALUE ts_terminate(VALUE self, VALUE v_task)
|
305
|
+
{
|
306
|
+
TSStruct* ptr;
|
307
|
+
HRESULT hr;
|
308
|
+
|
309
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
310
|
+
|
311
|
+
if(ptr->pITask == NULL)
|
312
|
+
rb_raise(cTSError, "fatal error: null pointer (ts_terminate)");
|
313
|
+
|
314
|
+
hr = ptr->pITask->Terminate();
|
315
|
+
|
316
|
+
if(FAILED(hr))
|
317
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
318
|
+
|
319
|
+
return self;
|
320
|
+
}
|
321
|
+
|
322
|
+
/*
|
323
|
+
* Sets the host on which the various task methods will execute.
|
324
|
+
*/
|
325
|
+
static VALUE ts_set_target_computer(VALUE self, VALUE v_host)
|
326
|
+
{
|
327
|
+
TSStruct* ptr;
|
328
|
+
HRESULT hr;
|
329
|
+
wchar_t cwszHostName[NAME_MAX];
|
330
|
+
|
331
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
332
|
+
StringValue(v_host);
|
333
|
+
|
334
|
+
if(ptr->pITS == NULL)
|
335
|
+
rb_raise(cTSError, "fatal error: null pointer (ts_set_target_computer");
|
336
|
+
|
337
|
+
MultiByteToWideChar(
|
338
|
+
CP_ACP,
|
339
|
+
0,
|
340
|
+
StringValuePtr(v_host),
|
341
|
+
RSTRING(v_host)->len + 1,
|
342
|
+
cwszHostName,
|
343
|
+
NAME_MAX
|
344
|
+
);
|
345
|
+
|
346
|
+
hr = ptr->pITS->SetTargetComputer(cwszHostName);
|
347
|
+
|
348
|
+
if(FAILED(hr))
|
349
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
350
|
+
|
351
|
+
return v_host;
|
352
|
+
}
|
353
|
+
|
354
|
+
/*
|
355
|
+
* call-seq:
|
356
|
+
* TaskScheduler#set_account_information(user, password)
|
357
|
+
*
|
358
|
+
* Sets the +user+ and +password+ for the given task. If the user and
|
359
|
+
* password are set properly true is returned. In some cases the job may
|
360
|
+
* be created, but the account information was bad. In this case the
|
361
|
+
* task is created but a warning is generated and false is returned.
|
362
|
+
*/
|
363
|
+
static VALUE ts_set_account_information(VALUE self, VALUE v_usr, VALUE v_pwd)
|
364
|
+
{
|
365
|
+
TSStruct* ptr;
|
366
|
+
HRESULT hr;
|
367
|
+
wchar_t cwszUsername[NAME_MAX];
|
368
|
+
wchar_t cwszPassword[NAME_MAX];
|
369
|
+
VALUE v_bool = Qtrue;
|
370
|
+
|
371
|
+
StringValue(v_usr);
|
372
|
+
StringValue(v_pwd);
|
373
|
+
|
374
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
375
|
+
check_ts_ptr(ptr, "ts_set_account_information");
|
376
|
+
|
377
|
+
if((NIL_P(v_usr) || RSTRING(v_usr)->len == 0)
|
378
|
+
&& (NIL_P(v_pwd) || RSTRING(v_pwd)->len == 0))
|
379
|
+
{
|
380
|
+
hr = ptr->pITask->SetAccountInformation(L"", NULL);
|
381
|
+
}
|
382
|
+
else{
|
383
|
+
|
384
|
+
MultiByteToWideChar(CP_ACP, 0, StringValuePtr(v_usr),
|
385
|
+
RSTRING(v_usr)->len+1, cwszUsername, NAME_MAX);
|
386
|
+
|
387
|
+
MultiByteToWideChar(CP_ACP, 0, StringValuePtr(v_pwd),
|
388
|
+
RSTRING(v_pwd)->len+1, cwszPassword, NAME_MAX);
|
389
|
+
|
390
|
+
hr = ptr->pITask->SetAccountInformation(cwszUsername, cwszPassword);
|
391
|
+
}
|
392
|
+
|
393
|
+
switch(hr){
|
394
|
+
case S_OK:
|
395
|
+
return Qtrue;
|
396
|
+
case E_ACCESSDENIED:
|
397
|
+
rb_raise(cTSError, "access denied");
|
398
|
+
break;
|
399
|
+
case E_INVALIDARG:
|
400
|
+
rb_raise(cTSError, "invalid argument");
|
401
|
+
break;
|
402
|
+
case E_OUTOFMEMORY:
|
403
|
+
rb_raise(cTSError, "out of memory");
|
404
|
+
break;
|
405
|
+
case SCHED_E_NO_SECURITY_SERVICES:
|
406
|
+
rb_raise(cTSError, "no security services on this platform");
|
407
|
+
break;
|
408
|
+
#ifdef SCHED_E_UNSUPPORTED_ACCOUNT_OPTION
|
409
|
+
case SCHED_E_UNSUPPORTED_ACCOUNT_OPTION:
|
410
|
+
rb_raise(cTSError, "unsupported account option");
|
411
|
+
break;
|
412
|
+
#endif
|
413
|
+
#ifdef SCHED_E_ACCOUNT_INFORMATION_NOT_SET
|
414
|
+
// Oddly, even if this error occurs, the job is still created, so
|
415
|
+
// we generate a warning instead of an error, but return false.
|
416
|
+
case SCHED_E_ACCOUNT_INFORMATION_NOT_SET:
|
417
|
+
rb_warn("job created, but password was invalid");
|
418
|
+
v_bool = Qfalse;
|
419
|
+
break;
|
420
|
+
#endif
|
421
|
+
default:
|
422
|
+
rb_raise(cTSError, "unknown error");
|
423
|
+
}
|
424
|
+
|
425
|
+
return v_bool;
|
426
|
+
}
|
427
|
+
|
428
|
+
/*
|
429
|
+
* Returns the user associated with the task or nil if no user has yet
|
430
|
+
* been associated with the task.
|
431
|
+
*/
|
432
|
+
static VALUE ts_get_account_information(VALUE self)
|
433
|
+
{
|
434
|
+
TSStruct* ptr;
|
435
|
+
HRESULT hr;
|
436
|
+
LPWSTR lpcwszUsername;
|
437
|
+
TCHAR user[NAME_MAX];
|
438
|
+
VALUE v_user;
|
439
|
+
|
440
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
441
|
+
check_ts_ptr(ptr, "ts_get_account_information");
|
442
|
+
|
443
|
+
hr = ptr->pITask->GetAccountInformation(&lpcwszUsername);
|
444
|
+
|
445
|
+
if((SUCCEEDED(hr)) && (hr != SCHED_E_NO_SECURITY_SERVICES)){
|
446
|
+
WideCharToMultiByte(
|
447
|
+
CP_ACP,
|
448
|
+
0,
|
449
|
+
lpcwszUsername,
|
450
|
+
-1,
|
451
|
+
user,
|
452
|
+
NAME_MAX,
|
453
|
+
NULL,
|
454
|
+
NULL
|
455
|
+
);
|
456
|
+
CoTaskMemFree(lpcwszUsername);
|
457
|
+
v_user = rb_str_new2(user);
|
458
|
+
}
|
459
|
+
else if(hr == SCHED_E_ACCOUNT_INFORMATION_NOT_SET){
|
460
|
+
v_user = Qnil;
|
461
|
+
}
|
462
|
+
else{
|
463
|
+
CoTaskMemFree(lpcwszUsername);
|
464
|
+
rb_raise(cTSError, ErrorString(hr));
|
465
|
+
}
|
466
|
+
|
467
|
+
return v_user;
|
468
|
+
}
|
469
|
+
|
470
|
+
/*
|
471
|
+
* Sets the application associated with the task.
|
472
|
+
*/
|
473
|
+
static VALUE ts_set_application_name(VALUE self, VALUE v_app)
|
474
|
+
{
|
475
|
+
TSStruct* ptr;
|
476
|
+
HRESULT hr;
|
477
|
+
wchar_t cwszAppname[NAME_MAX];
|
478
|
+
|
479
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
480
|
+
check_ts_ptr(ptr, "ts_set_application");
|
481
|
+
StringValue(v_app);
|
482
|
+
|
483
|
+
MultiByteToWideChar(
|
484
|
+
CP_ACP,
|
485
|
+
0,
|
486
|
+
StringValuePtr(v_app),
|
487
|
+
RSTRING(v_app)->len+1,
|
488
|
+
cwszAppname,
|
489
|
+
NAME_MAX
|
490
|
+
);
|
491
|
+
|
492
|
+
hr = ptr->pITask->SetApplicationName(cwszAppname);
|
493
|
+
|
494
|
+
if(FAILED(hr))
|
495
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
496
|
+
|
497
|
+
return v_app;
|
498
|
+
}
|
499
|
+
|
500
|
+
/*
|
501
|
+
* Returns the application name associated with the task.
|
502
|
+
*/
|
503
|
+
static VALUE ts_get_application_name(VALUE self)
|
504
|
+
{
|
505
|
+
TSStruct* ptr;
|
506
|
+
HRESULT hr;
|
507
|
+
LPWSTR lpcwszAppname;
|
508
|
+
TCHAR app[NAME_MAX];
|
509
|
+
|
510
|
+
Data_Get_Struct(self,TSStruct,ptr);
|
511
|
+
check_ts_ptr(ptr, "ts_get_application_name");
|
512
|
+
|
513
|
+
hr = ptr->pITask->GetApplicationName(&lpcwszAppname);
|
514
|
+
|
515
|
+
if(SUCCEEDED(hr)){
|
516
|
+
WideCharToMultiByte(CP_ACP, 0, lpcwszAppname, -1, app, NAME_MAX, NULL, NULL );
|
517
|
+
CoTaskMemFree(lpcwszAppname);
|
518
|
+
}
|
519
|
+
else{
|
520
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
521
|
+
}
|
522
|
+
|
523
|
+
return rb_str_new2(app);
|
524
|
+
}
|
525
|
+
|
526
|
+
/*
|
527
|
+
* Sets the parameters for the task. These parameters are passed as command
|
528
|
+
* line arguments to the application the task will run. To clear the command
|
529
|
+
* line parameters set it to an empty string.
|
530
|
+
*/
|
531
|
+
static VALUE ts_set_parameters(VALUE self, VALUE v_param)
|
532
|
+
{
|
533
|
+
TSStruct* ptr;
|
534
|
+
HRESULT hr;
|
535
|
+
wchar_t cwszParameters[NAME_MAX];
|
536
|
+
|
537
|
+
Data_Get_Struct(self,TSStruct,ptr);
|
538
|
+
check_ts_ptr(ptr, "ts_set_parameters");
|
539
|
+
StringValue(v_param);
|
540
|
+
|
541
|
+
MultiByteToWideChar(
|
542
|
+
CP_ACP,
|
543
|
+
0,
|
544
|
+
StringValuePtr(v_param),
|
545
|
+
RSTRING(v_param)->len+1,
|
546
|
+
cwszParameters,
|
547
|
+
NAME_MAX
|
548
|
+
);
|
549
|
+
|
550
|
+
hr = ptr->pITask->SetParameters(cwszParameters);
|
551
|
+
|
552
|
+
if(FAILED(hr))
|
553
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
554
|
+
|
555
|
+
return v_param;
|
556
|
+
}
|
557
|
+
|
558
|
+
/*
|
559
|
+
* Returns the parameters for the task.
|
560
|
+
*/
|
561
|
+
static VALUE ts_get_parameters(VALUE self)
|
562
|
+
{
|
563
|
+
TSStruct* ptr;
|
564
|
+
HRESULT hr;
|
565
|
+
LPWSTR lpcwszParameters;
|
566
|
+
TCHAR param[NAME_MAX];
|
567
|
+
|
568
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
569
|
+
check_ts_ptr(ptr, "ts_get_parameters");
|
570
|
+
|
571
|
+
hr = ptr->pITask->GetParameters(&lpcwszParameters);
|
572
|
+
|
573
|
+
if(SUCCEEDED(hr)){
|
574
|
+
WideCharToMultiByte(
|
575
|
+
CP_ACP,
|
576
|
+
0,
|
577
|
+
lpcwszParameters,
|
578
|
+
-1,
|
579
|
+
param,
|
580
|
+
NAME_MAX,
|
581
|
+
NULL,
|
582
|
+
NULL
|
583
|
+
);
|
584
|
+
CoTaskMemFree(lpcwszParameters);
|
585
|
+
}
|
586
|
+
else{
|
587
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
588
|
+
}
|
589
|
+
|
590
|
+
return rb_str_new2(param);
|
591
|
+
}
|
592
|
+
|
593
|
+
/*
|
594
|
+
* Sets the working directory for the task.
|
595
|
+
*/
|
596
|
+
static VALUE ts_set_working_directory(VALUE self, VALUE v_dir)
|
597
|
+
{
|
598
|
+
TSStruct* ptr;
|
599
|
+
HRESULT hr;
|
600
|
+
wchar_t cwszDirectory[NAME_MAX];
|
601
|
+
|
602
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
603
|
+
check_ts_ptr(ptr, "ts_set_working_directory");
|
604
|
+
StringValue(v_dir);
|
605
|
+
|
606
|
+
MultiByteToWideChar(
|
607
|
+
CP_ACP,
|
608
|
+
0,
|
609
|
+
StringValuePtr(v_dir),
|
610
|
+
RSTRING(v_dir)->len+1,
|
611
|
+
cwszDirectory,
|
612
|
+
NAME_MAX
|
613
|
+
);
|
614
|
+
|
615
|
+
hr = ptr->pITask->SetWorkingDirectory(cwszDirectory);
|
616
|
+
|
617
|
+
if(FAILED(hr))
|
618
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
619
|
+
|
620
|
+
return v_dir;
|
621
|
+
}
|
622
|
+
|
623
|
+
/*
|
624
|
+
* Returns the working directory for the task.
|
625
|
+
*/
|
626
|
+
static VALUE ts_get_working_directory(VALUE self)
|
627
|
+
{
|
628
|
+
TSStruct* ptr;
|
629
|
+
HRESULT hr;
|
630
|
+
LPWSTR lpcwszDirectory;
|
631
|
+
TCHAR dir[NAME_MAX];
|
632
|
+
|
633
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
634
|
+
check_ts_ptr(ptr, "ts_get_working_directory");
|
635
|
+
|
636
|
+
hr = ptr->pITask->GetWorkingDirectory(&lpcwszDirectory);
|
637
|
+
|
638
|
+
if(SUCCEEDED(hr)){
|
639
|
+
WideCharToMultiByte(
|
640
|
+
CP_ACP,
|
641
|
+
0,
|
642
|
+
lpcwszDirectory,
|
643
|
+
-1,
|
644
|
+
dir,
|
645
|
+
NAME_MAX,
|
646
|
+
NULL,
|
647
|
+
NULL
|
648
|
+
);
|
649
|
+
CoTaskMemFree(lpcwszDirectory);
|
650
|
+
}
|
651
|
+
else{
|
652
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
653
|
+
}
|
654
|
+
|
655
|
+
return rb_str_new2(dir);
|
656
|
+
}
|
657
|
+
|
658
|
+
/*
|
659
|
+
* Sets the priority for the task. This can be any one of REALTIME, HIGH,
|
660
|
+
* NORMAL, IDLE, ABOVE_NORMAL or BELOW_NORMAL.
|
661
|
+
*/
|
662
|
+
static VALUE ts_set_priority(VALUE self, VALUE v_priority)
|
663
|
+
{
|
664
|
+
TSStruct* ptr;
|
665
|
+
HRESULT hr;
|
666
|
+
DWORD dwPriority;
|
667
|
+
|
668
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
669
|
+
check_ts_ptr(ptr, "ts_set_priority");
|
670
|
+
|
671
|
+
dwPriority = NUM2UINT(v_priority);
|
672
|
+
|
673
|
+
hr = ptr->pITask->SetPriority(dwPriority);
|
674
|
+
|
675
|
+
if(FAILED(hr))
|
676
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
677
|
+
|
678
|
+
return v_priority;
|
679
|
+
}
|
680
|
+
|
681
|
+
/*
|
682
|
+
* Returns the priority for the class. The possibilities are 'realtime',
|
683
|
+
* 'high', 'normal', 'idle', 'above_normal', 'below_normal' and 'unknown'.
|
684
|
+
*/
|
685
|
+
static VALUE ts_get_priority(VALUE self)
|
686
|
+
{
|
687
|
+
TSStruct* ptr;
|
688
|
+
HRESULT hr;
|
689
|
+
DWORD dwPriority;
|
690
|
+
VALUE v_priority;
|
691
|
+
|
692
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
693
|
+
check_ts_ptr(ptr, "ts_get_priority");
|
694
|
+
|
695
|
+
hr = ptr->pITask->GetPriority(&dwPriority);
|
696
|
+
|
697
|
+
if(SUCCEEDED(hr)){
|
698
|
+
if(dwPriority & IDLE_PRIORITY_CLASS)
|
699
|
+
v_priority = rb_str_new2("idle");
|
700
|
+
|
701
|
+
if(dwPriority & NORMAL_PRIORITY_CLASS)
|
702
|
+
v_priority = rb_str_new2("normal");
|
703
|
+
|
704
|
+
if(dwPriority & HIGH_PRIORITY_CLASS)
|
705
|
+
v_priority = rb_str_new2("high");
|
706
|
+
|
707
|
+
if(dwPriority & REALTIME_PRIORITY_CLASS)
|
708
|
+
v_priority = rb_str_new2("realtime");
|
709
|
+
|
710
|
+
if(dwPriority & BELOW_NORMAL_PRIORITY_CLASS)
|
711
|
+
v_priority = rb_str_new2("below_normal");
|
712
|
+
|
713
|
+
if(dwPriority & ABOVE_NORMAL_PRIORITY_CLASS)
|
714
|
+
v_priority = rb_str_new2("above_normal");
|
715
|
+
|
716
|
+
v_priority = rb_str_new2("unknown");
|
717
|
+
}
|
718
|
+
else{
|
719
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
720
|
+
}
|
721
|
+
|
722
|
+
return v_priority;
|
723
|
+
}
|
724
|
+
|
725
|
+
/*
|
726
|
+
* Creates a new +work_item+ for the given +task+.
|
727
|
+
*/
|
728
|
+
static VALUE ts_new_work_item(VALUE self, VALUE v_task, VALUE v_trigger)
|
729
|
+
{
|
730
|
+
TSStruct* ptr;
|
731
|
+
HRESULT hr;
|
732
|
+
wchar_t cwszTaskName[NAME_MAX];
|
733
|
+
ITaskTrigger *pITaskTrigger;
|
734
|
+
WORD piNewTrigger;
|
735
|
+
TASK_TRIGGER pTrigger;
|
736
|
+
VALUE i, htmp;
|
737
|
+
|
738
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
739
|
+
Check_Type(v_trigger, T_HASH);
|
740
|
+
|
741
|
+
if(ptr->pITS == NULL)
|
742
|
+
rb_raise(cTSError, "null pointer error (ts_new_work_item)");
|
743
|
+
|
744
|
+
if(ptr->pITask != NULL){
|
745
|
+
ptr->pITask->Release();
|
746
|
+
ptr->pITask = NULL;
|
747
|
+
}
|
748
|
+
|
749
|
+
MultiByteToWideChar(
|
750
|
+
CP_ACP,
|
751
|
+
0,
|
752
|
+
StringValuePtr(v_task),
|
753
|
+
RSTRING(v_task)->len+1,
|
754
|
+
cwszTaskName,
|
755
|
+
NAME_MAX
|
756
|
+
);
|
757
|
+
|
758
|
+
hr = ptr->pITS->NewWorkItem(
|
759
|
+
cwszTaskName, // Name of task
|
760
|
+
CLSID_CTask, // Class identifier
|
761
|
+
IID_ITask, // Interface identifier
|
762
|
+
(IUnknown**)&(ptr->pITask) // Address of task interface
|
763
|
+
);
|
764
|
+
|
765
|
+
if(FAILED(hr)){
|
766
|
+
ptr->pITask = NULL; // added by phasis68 for ts_free prevent
|
767
|
+
rb_raise(cTSError, "NewWorkItem() function failed");
|
768
|
+
}
|
769
|
+
|
770
|
+
hr = ptr->pITask->CreateTrigger(&piNewTrigger, &pITaskTrigger);
|
771
|
+
|
772
|
+
if(FAILED(hr))
|
773
|
+
rb_raise(cTSError, "CreateTrigger() failed");
|
774
|
+
|
775
|
+
/*
|
776
|
+
* Define TASK_TRIGGER structure. Note that wBeginDay, wBeginMonth and
|
777
|
+
* wBeginYear must be set to a valid day, month, and year respectively.
|
778
|
+
*/
|
779
|
+
ZeroMemory(&pTrigger, sizeof(TASK_TRIGGER));
|
780
|
+
pTrigger.cbTriggerSize = sizeof(TASK_TRIGGER);
|
781
|
+
|
782
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("start_year"))) != Qnil)
|
783
|
+
pTrigger.wBeginYear = NUM2INT(i);
|
784
|
+
|
785
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("start_month"))) != Qnil)
|
786
|
+
pTrigger.wBeginMonth = NUM2INT(i);
|
787
|
+
|
788
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("start_day")))!=Qnil)
|
789
|
+
pTrigger.wBeginDay = NUM2INT(i);
|
790
|
+
|
791
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("end_year"))) != Qnil)
|
792
|
+
pTrigger.wEndYear = NUM2INT(i);
|
793
|
+
|
794
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("end_month"))) != Qnil)
|
795
|
+
pTrigger.wEndMonth = NUM2INT(i);
|
796
|
+
|
797
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("end_day"))) != Qnil)
|
798
|
+
pTrigger.wEndDay = NUM2INT(i);
|
799
|
+
|
800
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("start_hour"))) != Qnil)
|
801
|
+
pTrigger.wStartHour = NUM2INT(i);
|
802
|
+
|
803
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("start_minute"))) != Qnil)
|
804
|
+
pTrigger.wStartMinute = NUM2INT(i);
|
805
|
+
|
806
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("minutes_duration"))) != Qnil)
|
807
|
+
pTrigger.MinutesDuration = NUM2INT(i);
|
808
|
+
|
809
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("minutes_interval"))) != Qnil)
|
810
|
+
pTrigger.MinutesInterval = NUM2INT(i);
|
811
|
+
|
812
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("random_minutes_interval"))) != Qnil)
|
813
|
+
pTrigger.wRandomMinutesInterval = NUM2INT(i);
|
814
|
+
|
815
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("flags"))) != Qnil)
|
816
|
+
pTrigger.rgFlags = NUM2INT(i);
|
817
|
+
|
818
|
+
if((i = rb_hash_aref(v_trigger, rb_str_new2("trigger_type"))) != Qnil)
|
819
|
+
pTrigger.TriggerType = (TASK_TRIGGER_TYPE)NUM2INT(i);
|
820
|
+
|
821
|
+
htmp =rb_hash_aref(v_trigger, rb_str_new2("type"));
|
822
|
+
|
823
|
+
if(TYPE(htmp)!=T_HASH)
|
824
|
+
htmp = Qnil;
|
825
|
+
|
826
|
+
switch(pTrigger.TriggerType){
|
827
|
+
case TASK_TIME_TRIGGER_DAILY:
|
828
|
+
if(htmp != Qnil){
|
829
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days_interval"))) != Qnil)
|
830
|
+
pTrigger.Type.Daily.DaysInterval = NUM2INT(i);
|
831
|
+
}
|
832
|
+
break;
|
833
|
+
case TASK_TIME_TRIGGER_WEEKLY:
|
834
|
+
if(htmp != Qnil){
|
835
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("weeks_interval"))) != Qnil)
|
836
|
+
pTrigger.Type.Weekly.WeeksInterval = NUM2INT(i);
|
837
|
+
|
838
|
+
if((i=rb_hash_aref(htmp, rb_str_new2("days_of_week")))!=Qnil)
|
839
|
+
pTrigger.Type.Weekly.rgfDaysOfTheWeek = NUM2INT(i);
|
840
|
+
}
|
841
|
+
break;
|
842
|
+
case TASK_TIME_TRIGGER_MONTHLYDATE:
|
843
|
+
if(htmp != Qnil){
|
844
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("months"))) != Qnil)
|
845
|
+
pTrigger.Type.MonthlyDate.rgfMonths = NUM2INT(i);
|
846
|
+
|
847
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days"))) != Qnil)
|
848
|
+
pTrigger.Type.MonthlyDate.rgfDays = humanDaysToBitField(NUM2INT(i));
|
849
|
+
}
|
850
|
+
break;
|
851
|
+
case TASK_TIME_TRIGGER_MONTHLYDOW:
|
852
|
+
if(htmp != Qnil){
|
853
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("weeks"))) != Qnil)
|
854
|
+
pTrigger.Type.MonthlyDOW.wWhichWeek = NUM2INT(i);
|
855
|
+
|
856
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days_of_week"))) != Qnil)
|
857
|
+
pTrigger.Type.MonthlyDOW.rgfDaysOfTheWeek = NUM2INT(i);
|
858
|
+
|
859
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("months"))) != Qnil)
|
860
|
+
pTrigger.Type.MonthlyDOW.rgfMonths = NUM2INT(i);
|
861
|
+
}
|
862
|
+
break;
|
863
|
+
default:
|
864
|
+
rb_raise(cTSError, "Unknown trigger type");
|
865
|
+
}
|
866
|
+
|
867
|
+
hr = pITaskTrigger->SetTrigger (&pTrigger);
|
868
|
+
|
869
|
+
if(FAILED(hr))
|
870
|
+
rb_raise(cTSError, "SetTrigger() failed");
|
871
|
+
|
872
|
+
pITaskTrigger->Release();
|
873
|
+
|
874
|
+
return self;
|
875
|
+
}
|
876
|
+
|
877
|
+
/*
|
878
|
+
* Returns the number of triggers associated with the active task.
|
879
|
+
*/
|
880
|
+
static VALUE ts_get_trigger_count(VALUE self)
|
881
|
+
{
|
882
|
+
TSStruct* ptr;
|
883
|
+
HRESULT hr;
|
884
|
+
WORD TriggerCount;
|
885
|
+
VALUE v_count;
|
886
|
+
|
887
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
888
|
+
check_ts_ptr(ptr, "ts_get_trigger_count");
|
889
|
+
|
890
|
+
hr = ptr->pITask->GetTriggerCount(&TriggerCount);
|
891
|
+
|
892
|
+
if(SUCCEEDED(hr))
|
893
|
+
v_count = UINT2NUM(TriggerCount);
|
894
|
+
else
|
895
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
896
|
+
|
897
|
+
return v_count;
|
898
|
+
}
|
899
|
+
|
900
|
+
/*
|
901
|
+
* call-seq:
|
902
|
+
* TaskScheduler#trigger_string(index)
|
903
|
+
*
|
904
|
+
* Returns a string that describes the current trigger at the specified
|
905
|
+
* index for the active task.
|
906
|
+
*
|
907
|
+
* Example: "At 7:14 AM every day, starting 4/11/2009"
|
908
|
+
*
|
909
|
+
*/
|
910
|
+
static VALUE ts_get_trigger_string(VALUE self, VALUE v_index)
|
911
|
+
{
|
912
|
+
TSStruct* ptr;
|
913
|
+
HRESULT hr;
|
914
|
+
WORD TriggerIndex;
|
915
|
+
LPWSTR ppwszTrigger;
|
916
|
+
TCHAR buf[NAME_MAX];
|
917
|
+
|
918
|
+
Data_Get_Struct(self,TSStruct, ptr);
|
919
|
+
check_ts_ptr(ptr, "ts_get_trigger_string");
|
920
|
+
|
921
|
+
TriggerIndex = NUM2INT(v_index);
|
922
|
+
|
923
|
+
hr = ptr->pITask->GetTriggerString(TriggerIndex,&ppwszTrigger);
|
924
|
+
|
925
|
+
if(SUCCEEDED(hr)){
|
926
|
+
WideCharToMultiByte(
|
927
|
+
CP_ACP,
|
928
|
+
0,
|
929
|
+
ppwszTrigger,
|
930
|
+
-1,
|
931
|
+
buf,
|
932
|
+
NAME_MAX,
|
933
|
+
NULL,
|
934
|
+
NULL
|
935
|
+
);
|
936
|
+
CoTaskMemFree(ppwszTrigger);
|
937
|
+
}
|
938
|
+
else{
|
939
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
940
|
+
}
|
941
|
+
|
942
|
+
return rb_str_new2(buf);
|
943
|
+
}
|
944
|
+
|
945
|
+
/*
|
946
|
+
* call-seq:
|
947
|
+
* TaskScheduler#delete_trigger(index)
|
948
|
+
*
|
949
|
+
* Deletes the trigger at the specified +index+. Returns the index of the
|
950
|
+
* trigger that was deleted.
|
951
|
+
*/
|
952
|
+
static VALUE ts_delete_trigger(VALUE self, VALUE v_index)
|
953
|
+
{
|
954
|
+
TSStruct* ptr;
|
955
|
+
HRESULT hr;
|
956
|
+
WORD TriggerIndex;
|
957
|
+
|
958
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
959
|
+
check_ts_ptr(ptr, "ts_delete_trigger");
|
960
|
+
|
961
|
+
TriggerIndex = NUM2INT(v_index);
|
962
|
+
|
963
|
+
hr = ptr->pITask->DeleteTrigger(TriggerIndex);
|
964
|
+
|
965
|
+
if(FAILED(hr))
|
966
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
967
|
+
|
968
|
+
return v_index;
|
969
|
+
}
|
970
|
+
|
971
|
+
/*
|
972
|
+
* call-seq:
|
973
|
+
* TaskScheduler#trigger(index)
|
974
|
+
*
|
975
|
+
* Returns a hash that describes the trigger for the active task at the
|
976
|
+
* given +index+.
|
977
|
+
*/
|
978
|
+
static VALUE ts_get_trigger(VALUE self, VALUE index)
|
979
|
+
{
|
980
|
+
TSStruct* ptr;
|
981
|
+
HRESULT hr;
|
982
|
+
WORD TriggerIndex;
|
983
|
+
VALUE trigger,htmp;
|
984
|
+
ITaskTrigger *pITaskTrigger;
|
985
|
+
TASK_TRIGGER pTrigger;
|
986
|
+
|
987
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
988
|
+
check_ts_ptr(ptr, "ts_get_trigger");
|
989
|
+
|
990
|
+
TriggerIndex = NUM2INT(index);
|
991
|
+
|
992
|
+
hr = ptr->pITask->GetTrigger(TriggerIndex,&pITaskTrigger);
|
993
|
+
|
994
|
+
if(FAILED(hr))
|
995
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
996
|
+
|
997
|
+
ZeroMemory(&pTrigger, sizeof(TASK_TRIGGER));
|
998
|
+
pTrigger.cbTriggerSize = sizeof(TASK_TRIGGER);
|
999
|
+
|
1000
|
+
hr = pITaskTrigger->GetTrigger(&pTrigger);
|
1001
|
+
|
1002
|
+
if(FAILED(hr)){
|
1003
|
+
strcpy(error, ErrorString(GetLastError()));
|
1004
|
+
pITaskTrigger->Release();
|
1005
|
+
rb_raise(cTSError, error);
|
1006
|
+
}
|
1007
|
+
|
1008
|
+
trigger = rb_hash_new();
|
1009
|
+
|
1010
|
+
rb_hash_aset(trigger, rb_str_new2("start_year"),
|
1011
|
+
INT2NUM(pTrigger.wBeginYear));
|
1012
|
+
|
1013
|
+
rb_hash_aset(trigger, rb_str_new2("start_month"),
|
1014
|
+
INT2NUM(pTrigger.wBeginMonth));
|
1015
|
+
|
1016
|
+
rb_hash_aset(trigger, rb_str_new2("start_day"),
|
1017
|
+
INT2NUM(pTrigger.wBeginDay));
|
1018
|
+
|
1019
|
+
rb_hash_aset(trigger, rb_str_new2("end_year"),
|
1020
|
+
INT2NUM(pTrigger.wEndYear));
|
1021
|
+
|
1022
|
+
rb_hash_aset(trigger, rb_str_new2("end_month"),
|
1023
|
+
INT2NUM(pTrigger.wEndMonth));
|
1024
|
+
|
1025
|
+
rb_hash_aset(trigger, rb_str_new2("end_day"),
|
1026
|
+
INT2NUM(pTrigger.wEndDay));
|
1027
|
+
|
1028
|
+
rb_hash_aset(trigger, rb_str_new2("start_hour"),
|
1029
|
+
INT2NUM(pTrigger.wStartHour));
|
1030
|
+
|
1031
|
+
rb_hash_aset(trigger, rb_str_new2("start_minute"),
|
1032
|
+
INT2NUM(pTrigger.wStartMinute));
|
1033
|
+
|
1034
|
+
rb_hash_aset(trigger, rb_str_new2("minutes_duration"),
|
1035
|
+
INT2NUM(pTrigger.MinutesDuration));
|
1036
|
+
|
1037
|
+
rb_hash_aset(trigger, rb_str_new2("minutes_interval"),
|
1038
|
+
INT2NUM(pTrigger.MinutesInterval));
|
1039
|
+
|
1040
|
+
rb_hash_aset(trigger, rb_str_new2("trigger_type"),
|
1041
|
+
INT2NUM(pTrigger.TriggerType));
|
1042
|
+
|
1043
|
+
rb_hash_aset(trigger, rb_str_new2("random_minutes_interval"),
|
1044
|
+
INT2NUM(pTrigger.wRandomMinutesInterval));
|
1045
|
+
|
1046
|
+
rb_hash_aset(trigger, rb_str_new2("flags"),
|
1047
|
+
INT2NUM(pTrigger.rgFlags));
|
1048
|
+
|
1049
|
+
switch(pTrigger.TriggerType){
|
1050
|
+
case TASK_TIME_TRIGGER_DAILY:
|
1051
|
+
htmp = rb_hash_new();
|
1052
|
+
rb_hash_aset(htmp, rb_str_new2("days_interval"),
|
1053
|
+
INT2NUM(pTrigger.Type.Daily.DaysInterval));
|
1054
|
+
rb_hash_aset(trigger, rb_str_new2("type"), htmp);
|
1055
|
+
break;
|
1056
|
+
case TASK_TIME_TRIGGER_WEEKLY:
|
1057
|
+
htmp = rb_hash_new();
|
1058
|
+
rb_hash_aset(htmp, rb_str_new2("weeks_interval"),
|
1059
|
+
INT2NUM(pTrigger.Type.Weekly.WeeksInterval));
|
1060
|
+
rb_hash_aset(htmp, rb_str_new2("days_of_week"),
|
1061
|
+
INT2NUM(pTrigger.Type.Weekly.rgfDaysOfTheWeek));
|
1062
|
+
rb_hash_aset(trigger, rb_str_new2("type"), htmp);
|
1063
|
+
break;
|
1064
|
+
case TASK_TIME_TRIGGER_MONTHLYDATE:
|
1065
|
+
htmp = rb_hash_new();
|
1066
|
+
rb_hash_aset(htmp, rb_str_new2("days"),
|
1067
|
+
INT2NUM(bitFieldToHumanDays(pTrigger.Type.MonthlyDate.rgfDays)));
|
1068
|
+
rb_hash_aset(htmp, rb_str_new2("months"),
|
1069
|
+
INT2NUM(pTrigger.Type.MonthlyDate.rgfMonths));
|
1070
|
+
rb_hash_aset(trigger, rb_str_new2("type"), htmp);
|
1071
|
+
break;
|
1072
|
+
case TASK_TIME_TRIGGER_MONTHLYDOW:
|
1073
|
+
htmp = rb_hash_new();
|
1074
|
+
rb_hash_aset(htmp, rb_str_new2("weeks"),
|
1075
|
+
INT2NUM(bitFieldToHumanDays(pTrigger.Type.MonthlyDOW.wWhichWeek)));
|
1076
|
+
rb_hash_aset(htmp, rb_str_new2("days_of_week"),
|
1077
|
+
INT2NUM(pTrigger.Type.MonthlyDOW.rgfDaysOfTheWeek));
|
1078
|
+
rb_hash_aset(htmp, rb_str_new2("months"), INT2NUM(pTrigger.Type.MonthlyDOW.rgfMonths));
|
1079
|
+
rb_hash_aset(trigger, rb_str_new2("type"), htmp);
|
1080
|
+
break;
|
1081
|
+
default:
|
1082
|
+
rb_raise(cTSError, "Unknown trigger type");
|
1083
|
+
}
|
1084
|
+
|
1085
|
+
pITaskTrigger->Release();
|
1086
|
+
return trigger;
|
1087
|
+
}
|
1088
|
+
|
1089
|
+
/*
|
1090
|
+
* call-seq:
|
1091
|
+
* TaskScheduler#add_trigger(index, options)
|
1092
|
+
*
|
1093
|
+
* Adds the given trigger of hash +options+ at the specified +index+.
|
1094
|
+
*/
|
1095
|
+
static VALUE ts_add_trigger(VALUE self, VALUE index, VALUE trigger)
|
1096
|
+
{
|
1097
|
+
TSStruct* ptr;
|
1098
|
+
HRESULT hr;
|
1099
|
+
WORD TriggerIndex;
|
1100
|
+
ITaskTrigger *pITaskTrigger;
|
1101
|
+
TASK_TRIGGER pTrigger;
|
1102
|
+
VALUE i, htmp;
|
1103
|
+
|
1104
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1105
|
+
Check_Type(trigger, T_HASH);
|
1106
|
+
check_ts_ptr(ptr, "ts_add_trigger");
|
1107
|
+
|
1108
|
+
TriggerIndex = NUM2INT(index);
|
1109
|
+
|
1110
|
+
hr = ptr->pITask->GetTrigger(TriggerIndex,&pITaskTrigger);
|
1111
|
+
|
1112
|
+
if(FAILED(hr))
|
1113
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1114
|
+
|
1115
|
+
ZeroMemory(&pTrigger, sizeof(TASK_TRIGGER));
|
1116
|
+
|
1117
|
+
// Define TASK_TRIGGER structure. Note that wBeginDay, wBeginMonth and
|
1118
|
+
// wBeginYear must be set to a valid day, month, and year respectively.
|
1119
|
+
pTrigger.cbTriggerSize = sizeof(TASK_TRIGGER);
|
1120
|
+
|
1121
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("start_year"))) != Qnil)
|
1122
|
+
pTrigger.wBeginYear = NUM2INT(i);
|
1123
|
+
|
1124
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("start_month"))) != Qnil)
|
1125
|
+
pTrigger.wBeginMonth = NUM2INT(i);
|
1126
|
+
|
1127
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("start_day"))) != Qnil)
|
1128
|
+
pTrigger.wBeginDay = NUM2INT(i);
|
1129
|
+
|
1130
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("end_year"))) != Qnil)
|
1131
|
+
pTrigger.wEndYear = NUM2INT(i);
|
1132
|
+
|
1133
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("end_month"))) != Qnil)
|
1134
|
+
pTrigger.wEndMonth = NUM2INT(i);
|
1135
|
+
|
1136
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("end_day"))) != Qnil)
|
1137
|
+
pTrigger.wEndDay = NUM2INT(i);
|
1138
|
+
|
1139
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("start_hour"))) != Qnil)
|
1140
|
+
pTrigger.wStartHour = NUM2INT(i);
|
1141
|
+
|
1142
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("start_minute"))) != Qnil)
|
1143
|
+
pTrigger.wStartMinute = NUM2INT(i);
|
1144
|
+
|
1145
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("minutes_duration"))) != Qnil)
|
1146
|
+
pTrigger.MinutesDuration = NUM2INT(i);
|
1147
|
+
|
1148
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("minutes_interval"))) != Qnil)
|
1149
|
+
pTrigger.MinutesInterval = NUM2INT(i);
|
1150
|
+
|
1151
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("random_minutes_interval"))) != Qnil)
|
1152
|
+
pTrigger.wRandomMinutesInterval = NUM2INT(i);
|
1153
|
+
|
1154
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("flags"))) != Qnil)
|
1155
|
+
pTrigger.rgFlags = NUM2INT(i);
|
1156
|
+
|
1157
|
+
if((i = rb_hash_aref(trigger, rb_str_new2("trigger_type"))) != Qnil)
|
1158
|
+
pTrigger.TriggerType = (TASK_TRIGGER_TYPE)NUM2INT(i);
|
1159
|
+
|
1160
|
+
htmp = rb_hash_aref(trigger, rb_str_new2("type"));
|
1161
|
+
Check_Type(htmp, T_HASH);
|
1162
|
+
|
1163
|
+
switch(pTrigger.TriggerType){
|
1164
|
+
case TASK_TIME_TRIGGER_DAILY:
|
1165
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days_interval"))) != Qnil)
|
1166
|
+
pTrigger.Type.Daily.DaysInterval = NUM2INT(i);
|
1167
|
+
break;
|
1168
|
+
case TASK_TIME_TRIGGER_WEEKLY:
|
1169
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("weeks_interval"))) != Qnil)
|
1170
|
+
pTrigger.Type.Weekly.WeeksInterval = NUM2INT(i);
|
1171
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days_of_week"))) != Qnil)
|
1172
|
+
pTrigger.Type.Weekly.rgfDaysOfTheWeek = NUM2INT(i);
|
1173
|
+
break;
|
1174
|
+
case TASK_TIME_TRIGGER_MONTHLYDATE:
|
1175
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("months"))) != Qnil)
|
1176
|
+
pTrigger.Type.MonthlyDate.rgfMonths = NUM2INT(i);
|
1177
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days"))) != Qnil)
|
1178
|
+
pTrigger.Type.MonthlyDate.rgfDays = humanDaysToBitField(NUM2INT(i));
|
1179
|
+
break;
|
1180
|
+
case TASK_TIME_TRIGGER_MONTHLYDOW:
|
1181
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("weeks"))) != Qnil)
|
1182
|
+
pTrigger.Type.MonthlyDOW.wWhichWeek = NUM2INT(i);
|
1183
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days_of_week"))) != Qnil)
|
1184
|
+
pTrigger.Type.MonthlyDOW.rgfDaysOfTheWeek = NUM2INT(i);
|
1185
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("months"))) != Qnil)
|
1186
|
+
pTrigger.Type.MonthlyDOW.rgfMonths = NUM2INT(i);
|
1187
|
+
break;
|
1188
|
+
default:
|
1189
|
+
rb_raise(cTSError, "Unknown trigger type");
|
1190
|
+
}
|
1191
|
+
|
1192
|
+
hr = pITaskTrigger->SetTrigger(&pTrigger);
|
1193
|
+
|
1194
|
+
if(FAILED(hr))
|
1195
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1196
|
+
|
1197
|
+
pITaskTrigger->Release();
|
1198
|
+
|
1199
|
+
return Qtrue;
|
1200
|
+
}
|
1201
|
+
|
1202
|
+
/*
|
1203
|
+
* call-seq:
|
1204
|
+
* TaskScheduler#trigger=(options)
|
1205
|
+
*
|
1206
|
+
* Takes a hash of +options+ that set the various trigger values, i.e. when
|
1207
|
+
* and how often the task will run. Valid keys are:
|
1208
|
+
*
|
1209
|
+
* * start_year # Must be greater than or equal to current year
|
1210
|
+
* * start_month # 1-12
|
1211
|
+
* * start_day # 1-31
|
1212
|
+
* * start_hour # 0-23
|
1213
|
+
* * start_minute # 0-59
|
1214
|
+
* * end_year
|
1215
|
+
* * end_month
|
1216
|
+
* * end_day
|
1217
|
+
* * minutes_duration
|
1218
|
+
* * minutes_interval
|
1219
|
+
* * random_minutes_interval
|
1220
|
+
* * flags
|
1221
|
+
* * trigger_type
|
1222
|
+
* * type # A sub-hash
|
1223
|
+
*
|
1224
|
+
* The 'trigger_type' determines what values are valid for the 'type'
|
1225
|
+
* key. They are as follows:
|
1226
|
+
*
|
1227
|
+
* Trigger Type Valid 'type' keys
|
1228
|
+
* ------------ ---------------------
|
1229
|
+
* DAILY days_interval
|
1230
|
+
* WEEKLY weeks_interval, days_of_week
|
1231
|
+
* MONTHLY_DATE months, days
|
1232
|
+
* MONTHLY_DOW weeks, days_of_week, months
|
1233
|
+
*--
|
1234
|
+
* TODO: Allow symbols or strings.
|
1235
|
+
*/
|
1236
|
+
static VALUE ts_set_trigger(VALUE self, VALUE v_opts)
|
1237
|
+
{
|
1238
|
+
TSStruct* ptr;
|
1239
|
+
HRESULT hr;
|
1240
|
+
WORD TriggerIndex;
|
1241
|
+
ITaskTrigger *pITaskTrigger;
|
1242
|
+
TASK_TRIGGER pTrigger;
|
1243
|
+
VALUE i, htmp;
|
1244
|
+
|
1245
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1246
|
+
Check_Type(v_opts, T_HASH);
|
1247
|
+
check_ts_ptr(ptr, "ts_set_trigger");
|
1248
|
+
|
1249
|
+
hr = ptr->pITask->CreateTrigger(&TriggerIndex, &pITaskTrigger);
|
1250
|
+
|
1251
|
+
if(FAILED(hr))
|
1252
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1253
|
+
|
1254
|
+
ZeroMemory(&pTrigger, sizeof(TASK_TRIGGER));
|
1255
|
+
|
1256
|
+
// Define TASK_TRIGGER structure. Note that wBeginDay, wBeginMonth, and
|
1257
|
+
// wBeginYear must be set to a valid day, month, and year respectively.
|
1258
|
+
pTrigger.cbTriggerSize = sizeof(TASK_TRIGGER);
|
1259
|
+
|
1260
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("start_year"))) != Qnil)
|
1261
|
+
pTrigger.wBeginYear = NUM2INT(i);
|
1262
|
+
|
1263
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("start_month"))) != Qnil)
|
1264
|
+
pTrigger.wBeginMonth = NUM2INT(i);
|
1265
|
+
|
1266
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("start_day"))) != Qnil)
|
1267
|
+
pTrigger.wBeginDay = NUM2INT(i);
|
1268
|
+
|
1269
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("end_year"))) != Qnil)
|
1270
|
+
pTrigger.wEndYear = NUM2INT(i);
|
1271
|
+
|
1272
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("end_month"))) != Qnil)
|
1273
|
+
pTrigger.wEndMonth = NUM2INT(i);
|
1274
|
+
|
1275
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("end_day"))) != Qnil)
|
1276
|
+
pTrigger.wEndDay = NUM2INT(i);
|
1277
|
+
|
1278
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("start_hour"))) != Qnil)
|
1279
|
+
pTrigger.wStartHour = NUM2INT(i);
|
1280
|
+
|
1281
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("start_minute"))) != Qnil)
|
1282
|
+
pTrigger.wStartMinute = NUM2INT(i);
|
1283
|
+
|
1284
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("minutes_duration"))) != Qnil)
|
1285
|
+
pTrigger.MinutesDuration = NUM2INT(i);
|
1286
|
+
|
1287
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("minutes_interval"))) != Qnil)
|
1288
|
+
pTrigger.MinutesInterval = NUM2INT(i);
|
1289
|
+
|
1290
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("random_minutes_interval"))) != Qnil)
|
1291
|
+
pTrigger.wRandomMinutesInterval = NUM2INT(i);
|
1292
|
+
|
1293
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("flags"))) != Qnil)
|
1294
|
+
pTrigger.rgFlags = NUM2INT(i);
|
1295
|
+
|
1296
|
+
if((i = rb_hash_aref(v_opts, rb_str_new2("trigger_type")))!=Qnil)
|
1297
|
+
pTrigger.TriggerType = (TASK_TRIGGER_TYPE)NUM2INT(i);
|
1298
|
+
|
1299
|
+
htmp = rb_hash_aref(v_opts, rb_str_new2("type"));
|
1300
|
+
|
1301
|
+
if(htmp != Qnil)
|
1302
|
+
Check_Type(htmp, T_HASH);
|
1303
|
+
|
1304
|
+
switch(pTrigger.TriggerType) {
|
1305
|
+
case TASK_TIME_TRIGGER_DAILY:
|
1306
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days_interval"))) != Qnil)
|
1307
|
+
pTrigger.Type.Daily.DaysInterval = NUM2INT(i);
|
1308
|
+
|
1309
|
+
break;
|
1310
|
+
case TASK_TIME_TRIGGER_WEEKLY:
|
1311
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("weeks_interval"))) != Qnil)
|
1312
|
+
pTrigger.Type.Weekly.WeeksInterval = NUM2INT(i);
|
1313
|
+
|
1314
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days_of_week"))) != Qnil)
|
1315
|
+
pTrigger.Type.Weekly.rgfDaysOfTheWeek = NUM2INT(i);
|
1316
|
+
|
1317
|
+
break;
|
1318
|
+
case TASK_TIME_TRIGGER_MONTHLYDATE:
|
1319
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("months"))) != Qnil)
|
1320
|
+
pTrigger.Type.MonthlyDate.rgfMonths = NUM2INT(i);
|
1321
|
+
|
1322
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days"))) != Qnil)
|
1323
|
+
pTrigger.Type.MonthlyDate.rgfDays = humanDaysToBitField(NUM2INT(i));
|
1324
|
+
|
1325
|
+
break;
|
1326
|
+
case TASK_TIME_TRIGGER_MONTHLYDOW:
|
1327
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("weeks"))) != Qnil)
|
1328
|
+
pTrigger.Type.MonthlyDOW.wWhichWeek = NUM2INT(i);
|
1329
|
+
|
1330
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("days_of_week"))) != Qnil)
|
1331
|
+
pTrigger.Type.MonthlyDOW.rgfDaysOfTheWeek = NUM2INT(i);
|
1332
|
+
|
1333
|
+
if((i = rb_hash_aref(htmp, rb_str_new2("months"))) != Qnil)
|
1334
|
+
pTrigger.Type.MonthlyDOW.rgfMonths = NUM2INT(i);
|
1335
|
+
break;
|
1336
|
+
default:
|
1337
|
+
rb_raise(cTSError, "Unknown trigger type");
|
1338
|
+
}
|
1339
|
+
|
1340
|
+
hr = pITaskTrigger->SetTrigger(&pTrigger);
|
1341
|
+
|
1342
|
+
if(FAILED(hr))
|
1343
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1344
|
+
|
1345
|
+
pITaskTrigger->Release();
|
1346
|
+
|
1347
|
+
return v_opts;
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
/*
|
1351
|
+
* Sets an OR'd value of flags that modify the behavior of the work item.
|
1352
|
+
*/
|
1353
|
+
static VALUE ts_set_flags(VALUE self, VALUE v_flags)
|
1354
|
+
{
|
1355
|
+
TSStruct* ptr;
|
1356
|
+
HRESULT hr;
|
1357
|
+
DWORD dwFlags;
|
1358
|
+
|
1359
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1360
|
+
|
1361
|
+
check_ts_ptr(ptr, "ts_set_flags");
|
1362
|
+
|
1363
|
+
dwFlags = NUM2UINT(v_flags);
|
1364
|
+
|
1365
|
+
hr = ptr->pITask->SetFlags(dwFlags);
|
1366
|
+
|
1367
|
+
if(FAILED(hr))
|
1368
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1369
|
+
|
1370
|
+
return v_flags;
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
/*
|
1374
|
+
* Returns the flags (integer) that modify the behavior of the work item. You
|
1375
|
+
* must OR the return value to determine the flags yourself.
|
1376
|
+
*--
|
1377
|
+
* TODO: Change this to an array of strings. There aren't that many.
|
1378
|
+
*/
|
1379
|
+
static VALUE ts_get_flags(VALUE self)
|
1380
|
+
{
|
1381
|
+
TSStruct* ptr;
|
1382
|
+
HRESULT hr;
|
1383
|
+
DWORD dwFlags;
|
1384
|
+
VALUE v_flags;
|
1385
|
+
|
1386
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1387
|
+
|
1388
|
+
check_ts_ptr(ptr, "ts_get_flags");
|
1389
|
+
|
1390
|
+
hr = ptr->pITask->GetFlags(&dwFlags);
|
1391
|
+
|
1392
|
+
if(SUCCEEDED(hr))
|
1393
|
+
v_flags = UINT2NUM(dwFlags);
|
1394
|
+
else
|
1395
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1396
|
+
|
1397
|
+
return v_flags;
|
1398
|
+
}
|
1399
|
+
|
1400
|
+
/*
|
1401
|
+
* Returns the status of the current task. The possible return values are
|
1402
|
+
* "ready", "running", "not scheduled" or "unknown", though the latter should
|
1403
|
+
* never occur.
|
1404
|
+
*
|
1405
|
+
* In the case of "not scheduled", it means that one or more of the properties
|
1406
|
+
* that are needed to run the work item on a schedule have not been set.
|
1407
|
+
*/
|
1408
|
+
static VALUE ts_get_status(VALUE self)
|
1409
|
+
{
|
1410
|
+
TSStruct* ptr;
|
1411
|
+
HRESULT hr;
|
1412
|
+
HRESULT st;
|
1413
|
+
VALUE v_status;
|
1414
|
+
|
1415
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1416
|
+
|
1417
|
+
check_ts_ptr(ptr, "ts_get_status");
|
1418
|
+
|
1419
|
+
hr = ptr->pITask->GetStatus(&st);
|
1420
|
+
|
1421
|
+
if(SUCCEEDED(hr)){
|
1422
|
+
switch((DWORD)st){
|
1423
|
+
case SCHED_S_TASK_READY:
|
1424
|
+
v_status = rb_str_new2("ready");
|
1425
|
+
break;
|
1426
|
+
case SCHED_S_TASK_RUNNING:
|
1427
|
+
v_status = rb_str_new2("running");
|
1428
|
+
break;
|
1429
|
+
case SCHED_S_TASK_NOT_SCHEDULED:
|
1430
|
+
v_status = rb_str_new2("not scheduled");
|
1431
|
+
break;
|
1432
|
+
default:
|
1433
|
+
v_status = rb_str_new2("unknown");
|
1434
|
+
};
|
1435
|
+
}
|
1436
|
+
else{
|
1437
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1438
|
+
}
|
1439
|
+
|
1440
|
+
return v_status;
|
1441
|
+
}
|
1442
|
+
|
1443
|
+
/*
|
1444
|
+
* Returns the exit code from when it last attempted to run the task.
|
1445
|
+
*/
|
1446
|
+
static VALUE ts_get_exit_code(VALUE self)
|
1447
|
+
{
|
1448
|
+
TSStruct* ptr;
|
1449
|
+
HRESULT hr;
|
1450
|
+
DWORD dwCode;
|
1451
|
+
VALUE v_exit_code;
|
1452
|
+
|
1453
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1454
|
+
|
1455
|
+
check_ts_ptr(ptr, "ts_get_exit_code");
|
1456
|
+
|
1457
|
+
hr = ptr->pITask->GetExitCode(&dwCode);
|
1458
|
+
|
1459
|
+
if(SUCCEEDED(hr))
|
1460
|
+
v_exit_code = UINT2NUM(dwCode);
|
1461
|
+
else
|
1462
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1463
|
+
|
1464
|
+
return v_exit_code;
|
1465
|
+
}
|
1466
|
+
|
1467
|
+
/*
|
1468
|
+
* Sets the comment associated with the task.
|
1469
|
+
*/
|
1470
|
+
static VALUE ts_set_comment(VALUE self, VALUE v_comment)
|
1471
|
+
{
|
1472
|
+
TSStruct* ptr;
|
1473
|
+
HRESULT hr;
|
1474
|
+
wchar_t buf[NAME_MAX];
|
1475
|
+
|
1476
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1477
|
+
check_ts_ptr(ptr, "ts_set_comment");
|
1478
|
+
StringValue(v_comment);
|
1479
|
+
|
1480
|
+
MultiByteToWideChar(
|
1481
|
+
CP_ACP,
|
1482
|
+
0,
|
1483
|
+
StringValuePtr(v_comment),
|
1484
|
+
RSTRING(v_comment)->len + 1,
|
1485
|
+
buf,
|
1486
|
+
NAME_MAX
|
1487
|
+
);
|
1488
|
+
|
1489
|
+
hr = ptr->pITask->SetComment(buf);
|
1490
|
+
|
1491
|
+
if(FAILED(hr))
|
1492
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1493
|
+
|
1494
|
+
return v_comment;
|
1495
|
+
}
|
1496
|
+
|
1497
|
+
/*
|
1498
|
+
* Returns the comment associated with the task.
|
1499
|
+
*/
|
1500
|
+
static VALUE ts_get_comment(VALUE self)
|
1501
|
+
{
|
1502
|
+
TSStruct* ptr;
|
1503
|
+
HRESULT hr;
|
1504
|
+
LPWSTR lpComment;
|
1505
|
+
TCHAR buf[NAME_MAX];
|
1506
|
+
VALUE v_comment;
|
1507
|
+
|
1508
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1509
|
+
|
1510
|
+
check_ts_ptr(ptr, "ts_get_comment");
|
1511
|
+
|
1512
|
+
hr = ptr->pITask->GetComment(&lpComment);
|
1513
|
+
|
1514
|
+
if(SUCCEEDED(hr))
|
1515
|
+
{
|
1516
|
+
WideCharToMultiByte(CP_ACP, 0, lpComment, -1, buf, NAME_MAX, NULL, NULL);
|
1517
|
+
CoTaskMemFree(lpComment);
|
1518
|
+
v_comment = rb_str_new2(buf);
|
1519
|
+
}
|
1520
|
+
else{
|
1521
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1522
|
+
}
|
1523
|
+
|
1524
|
+
return v_comment;
|
1525
|
+
}
|
1526
|
+
|
1527
|
+
/*
|
1528
|
+
* Sets the name of the user who created the task.
|
1529
|
+
*/
|
1530
|
+
static VALUE ts_set_creator(VALUE self, VALUE v_creator){
|
1531
|
+
TSStruct* ptr;
|
1532
|
+
HRESULT hr;
|
1533
|
+
wchar_t cwszCreator[NAME_MAX];
|
1534
|
+
|
1535
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1536
|
+
check_ts_ptr(ptr, "ts_set_creator");
|
1537
|
+
StringValue(v_creator);
|
1538
|
+
|
1539
|
+
MultiByteToWideChar(
|
1540
|
+
CP_ACP,
|
1541
|
+
0,
|
1542
|
+
StringValuePtr(v_creator),
|
1543
|
+
RSTRING(v_creator)->len + 1,
|
1544
|
+
cwszCreator,
|
1545
|
+
NAME_MAX
|
1546
|
+
);
|
1547
|
+
|
1548
|
+
hr = ptr->pITask->SetCreator(cwszCreator);
|
1549
|
+
|
1550
|
+
if(FAILED(hr))
|
1551
|
+
rb_raise(cTSError,ErrorString(GetLastError()));
|
1552
|
+
|
1553
|
+
return v_creator;
|
1554
|
+
}
|
1555
|
+
|
1556
|
+
/*
|
1557
|
+
* Returns the name of the user who created the task.
|
1558
|
+
*/
|
1559
|
+
static VALUE ts_get_creator(VALUE self){
|
1560
|
+
TSStruct* ptr;
|
1561
|
+
HRESULT hr;
|
1562
|
+
LPWSTR lpCreator;
|
1563
|
+
TCHAR crt[NAME_MAX];
|
1564
|
+
VALUE v_creator;
|
1565
|
+
|
1566
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1567
|
+
|
1568
|
+
check_ts_ptr(ptr, "ts_get_creator");
|
1569
|
+
|
1570
|
+
hr = ptr->pITask->GetCreator(&lpCreator);
|
1571
|
+
|
1572
|
+
if(SUCCEEDED(hr)){
|
1573
|
+
WideCharToMultiByte(CP_ACP, 0, lpCreator, -1, crt, NAME_MAX, NULL, NULL);
|
1574
|
+
CoTaskMemFree(lpCreator);
|
1575
|
+
v_creator = rb_str_new2(crt);
|
1576
|
+
}
|
1577
|
+
else{
|
1578
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1579
|
+
}
|
1580
|
+
|
1581
|
+
return v_creator;
|
1582
|
+
}
|
1583
|
+
|
1584
|
+
/*
|
1585
|
+
* Returns a Time object that indicates the next time the scheduled task
|
1586
|
+
* will run.
|
1587
|
+
*/
|
1588
|
+
static VALUE ts_get_next_run_time(VALUE self)
|
1589
|
+
{
|
1590
|
+
TSStruct* ptr;
|
1591
|
+
HRESULT hr;
|
1592
|
+
SYSTEMTIME nextRun;
|
1593
|
+
VALUE argv[7];
|
1594
|
+
VALUE v_time;
|
1595
|
+
|
1596
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1597
|
+
|
1598
|
+
check_ts_ptr(ptr, "ts_get_next_run_time");
|
1599
|
+
|
1600
|
+
hr = ptr->pITask->GetNextRunTime(&nextRun);
|
1601
|
+
|
1602
|
+
if(SUCCEEDED(hr)){
|
1603
|
+
argv[0] = INT2NUM(nextRun.wYear);
|
1604
|
+
argv[1] = INT2NUM(nextRun.wMonth);
|
1605
|
+
argv[2] = INT2NUM(nextRun.wDay);
|
1606
|
+
argv[3] = INT2NUM(nextRun.wHour);
|
1607
|
+
argv[4] = INT2NUM(nextRun.wMinute);
|
1608
|
+
argv[5] = INT2NUM(nextRun.wSecond);
|
1609
|
+
argv[6] = INT2NUM(nextRun.wMilliseconds * 1000);
|
1610
|
+
v_time = rb_funcall2(rb_cTime, rb_intern("local"), 7, argv);
|
1611
|
+
}
|
1612
|
+
else{
|
1613
|
+
rb_raise(cTSError,ErrorString(GetLastError()));
|
1614
|
+
}
|
1615
|
+
|
1616
|
+
return v_time;
|
1617
|
+
}
|
1618
|
+
|
1619
|
+
/*
|
1620
|
+
* Returns a Time object indicating the most recent time the task ran or
|
1621
|
+
* nil if the task has never run.
|
1622
|
+
*/
|
1623
|
+
static VALUE ts_get_most_recent_run_time(VALUE self)
|
1624
|
+
{
|
1625
|
+
TSStruct* ptr;
|
1626
|
+
HRESULT hr;
|
1627
|
+
SYSTEMTIME lastRun;
|
1628
|
+
VALUE argv[7];
|
1629
|
+
VALUE v_time;
|
1630
|
+
|
1631
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1632
|
+
|
1633
|
+
check_ts_ptr(ptr, "ts_get_most_recent_run_time");
|
1634
|
+
|
1635
|
+
hr = ptr->pITask->GetMostRecentRunTime(&lastRun);
|
1636
|
+
|
1637
|
+
if(SCHED_S_TASK_HAS_NOT_RUN == hr){
|
1638
|
+
v_time = Qnil;
|
1639
|
+
}
|
1640
|
+
else if(SUCCEEDED(hr)){
|
1641
|
+
argv[0] = INT2NUM(lastRun.wYear);
|
1642
|
+
argv[1] = INT2NUM(lastRun.wMonth);
|
1643
|
+
argv[2] = INT2NUM(lastRun.wDay);
|
1644
|
+
argv[3] = INT2NUM(lastRun.wHour);
|
1645
|
+
argv[4] = INT2NUM(lastRun.wMinute);
|
1646
|
+
argv[5] = INT2NUM(lastRun.wSecond);
|
1647
|
+
argv[6] = INT2NUM(lastRun.wMilliseconds * 1000);
|
1648
|
+
v_time = rb_funcall2(rb_cTime, rb_intern("local"), 7, argv);
|
1649
|
+
}
|
1650
|
+
else{
|
1651
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1652
|
+
}
|
1653
|
+
|
1654
|
+
return v_time;
|
1655
|
+
}
|
1656
|
+
|
1657
|
+
/*
|
1658
|
+
* Sets the maximum length of time, in milliseconds, that the task can run
|
1659
|
+
* before terminating. Returns the value you specified if successful.
|
1660
|
+
*/
|
1661
|
+
static VALUE ts_set_max_run_time(VALUE self, VALUE v_max_run_time)
|
1662
|
+
{
|
1663
|
+
TSStruct* ptr;
|
1664
|
+
HRESULT hr;
|
1665
|
+
DWORD maxRunTimeMilliSeconds;
|
1666
|
+
|
1667
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1668
|
+
|
1669
|
+
check_ts_ptr(ptr, "ts_set_max_run_time");
|
1670
|
+
|
1671
|
+
maxRunTimeMilliSeconds = NUM2UINT(v_max_run_time);
|
1672
|
+
|
1673
|
+
hr = ptr->pITask->SetMaxRunTime(maxRunTimeMilliSeconds);
|
1674
|
+
|
1675
|
+
if(FAILED(hr))
|
1676
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1677
|
+
|
1678
|
+
return v_max_run_time;
|
1679
|
+
}
|
1680
|
+
|
1681
|
+
/*
|
1682
|
+
* Returns the maximum length of time, in milliseconds, the task can run
|
1683
|
+
* before terminating.
|
1684
|
+
*/
|
1685
|
+
static VALUE ts_get_max_run_time(VALUE self)
|
1686
|
+
{
|
1687
|
+
TSStruct* ptr;
|
1688
|
+
HRESULT hr;
|
1689
|
+
DWORD maxRunTimeMilliSeconds;
|
1690
|
+
VALUE v_max_run_time;
|
1691
|
+
|
1692
|
+
Data_Get_Struct(self, TSStruct, ptr);
|
1693
|
+
|
1694
|
+
check_ts_ptr(ptr, "ts_get_max_run_time");
|
1695
|
+
|
1696
|
+
hr = ptr->pITask->GetMaxRunTime(&maxRunTimeMilliSeconds);
|
1697
|
+
|
1698
|
+
if(SUCCEEDED(hr))
|
1699
|
+
v_max_run_time = UINT2NUM(maxRunTimeMilliSeconds);
|
1700
|
+
else
|
1701
|
+
rb_raise(cTSError, ErrorString(GetLastError()));
|
1702
|
+
|
1703
|
+
return v_max_run_time;
|
1704
|
+
}
|
1705
|
+
|
1706
|
+
/*
|
1707
|
+
* The TaskScheduler class encapsulates the MS Windows task scheduler,
|
1708
|
+
* with which you can create, modify and delete new tasks.
|
1709
|
+
*/
|
1710
|
+
void Init_taskscheduler()
|
1711
|
+
{
|
1712
|
+
VALUE mWin32, cTaskScheduler;;
|
1713
|
+
|
1714
|
+
// The C++ code requires explicit function casting via 'VALUEFUNC'
|
1715
|
+
|
1716
|
+
// Modules and classes
|
1717
|
+
|
1718
|
+
/* The Win32 module serves as a toplevel namespace only */
|
1719
|
+
mWin32 = rb_define_module("Win32");
|
1720
|
+
|
1721
|
+
/* The TaskScheduler class encapsulates tasks related to the
|
1722
|
+
* Windows task scheduler */
|
1723
|
+
cTaskScheduler = rb_define_class_under(mWin32, "TaskScheduler", rb_cObject);
|
1724
|
+
|
1725
|
+
/* The TaskScheduler::Error class is raised whenever an operation related
|
1726
|
+
* the task scheduler fails.
|
1727
|
+
*/
|
1728
|
+
cTSError = rb_define_class_under(cTaskScheduler, "Error", rb_eStandardError);
|
1729
|
+
|
1730
|
+
// Taskscheduler class and instance methods
|
1731
|
+
|
1732
|
+
rb_define_alloc_func(cTaskScheduler, ts_allocate);
|
1733
|
+
rb_define_method(cTaskScheduler, "initialize", VALUEFUNC(ts_init), -1);
|
1734
|
+
rb_define_method(cTaskScheduler, "enum", VALUEFUNC(ts_enum), 0);
|
1735
|
+
rb_define_method(cTaskScheduler, "activate", VALUEFUNC(ts_activate), 1);
|
1736
|
+
rb_define_method(cTaskScheduler, "delete", VALUEFUNC(ts_delete), 1);
|
1737
|
+
rb_define_method(cTaskScheduler, "run", VALUEFUNC(ts_run), 0);
|
1738
|
+
rb_define_method(cTaskScheduler, "save", VALUEFUNC(ts_save), -1);
|
1739
|
+
rb_define_method(cTaskScheduler, "terminate", VALUEFUNC(ts_terminate), 0);
|
1740
|
+
|
1741
|
+
rb_define_method(cTaskScheduler, "machine=",
|
1742
|
+
VALUEFUNC(ts_set_target_computer), 1);
|
1743
|
+
|
1744
|
+
rb_define_method(cTaskScheduler, "set_account_information",
|
1745
|
+
VALUEFUNC(ts_set_account_information), 2);
|
1746
|
+
|
1747
|
+
rb_define_method(cTaskScheduler, "account_information",
|
1748
|
+
VALUEFUNC(ts_get_account_information), 0);
|
1749
|
+
|
1750
|
+
rb_define_method(cTaskScheduler, "application_name",
|
1751
|
+
VALUEFUNC(ts_get_application_name), 0);
|
1752
|
+
|
1753
|
+
rb_define_method(cTaskScheduler, "application_name=",
|
1754
|
+
VALUEFUNC(ts_set_application_name), 1);
|
1755
|
+
|
1756
|
+
rb_define_method(cTaskScheduler, "parameters",
|
1757
|
+
VALUEFUNC(ts_get_parameters), 0);
|
1758
|
+
|
1759
|
+
rb_define_method(cTaskScheduler, "parameters=",
|
1760
|
+
VALUEFUNC(ts_set_parameters), 1);
|
1761
|
+
|
1762
|
+
rb_define_method(cTaskScheduler, "working_directory",
|
1763
|
+
VALUEFUNC(ts_get_working_directory), 0);
|
1764
|
+
|
1765
|
+
rb_define_method(cTaskScheduler, "working_directory=",
|
1766
|
+
VALUEFUNC(ts_set_working_directory), 1);
|
1767
|
+
|
1768
|
+
rb_define_method(cTaskScheduler, "priority",
|
1769
|
+
VALUEFUNC(ts_get_priority), 0);
|
1770
|
+
|
1771
|
+
rb_define_method(cTaskScheduler, "priority=",
|
1772
|
+
VALUEFUNC(ts_set_priority), 1);
|
1773
|
+
|
1774
|
+
rb_define_method(cTaskScheduler, "new_work_item",
|
1775
|
+
VALUEFUNC(ts_new_work_item), 2);
|
1776
|
+
|
1777
|
+
rb_define_alias(cTaskScheduler, "new_task", "new_work_item");
|
1778
|
+
|
1779
|
+
// Trigger related methods
|
1780
|
+
|
1781
|
+
rb_define_method(cTaskScheduler, "trigger_count",
|
1782
|
+
VALUEFUNC(ts_get_trigger_count), 0);
|
1783
|
+
|
1784
|
+
rb_define_method(cTaskScheduler, "trigger_string",
|
1785
|
+
VALUEFUNC(ts_get_trigger_string), 1);
|
1786
|
+
|
1787
|
+
rb_define_method(cTaskScheduler, "delete_trigger",
|
1788
|
+
VALUEFUNC(ts_delete_trigger), 1);
|
1789
|
+
|
1790
|
+
rb_define_method(cTaskScheduler, "trigger",
|
1791
|
+
VALUEFUNC(ts_get_trigger), 1);
|
1792
|
+
|
1793
|
+
rb_define_method(cTaskScheduler, "trigger=",
|
1794
|
+
VALUEFUNC(ts_set_trigger), 1);
|
1795
|
+
|
1796
|
+
rb_define_method(cTaskScheduler, "add_trigger",
|
1797
|
+
VALUEFUNC(ts_add_trigger), 2);
|
1798
|
+
|
1799
|
+
rb_define_method(cTaskScheduler, "flags",
|
1800
|
+
VALUEFUNC(ts_get_flags), 0);
|
1801
|
+
|
1802
|
+
rb_define_method(cTaskScheduler, "flags=",
|
1803
|
+
VALUEFUNC(ts_set_flags), 1);
|
1804
|
+
|
1805
|
+
rb_define_method(cTaskScheduler, "status",
|
1806
|
+
VALUEFUNC(ts_get_status), 0);
|
1807
|
+
|
1808
|
+
rb_define_method(cTaskScheduler, "exit_code",
|
1809
|
+
VALUEFUNC(ts_get_exit_code), 0);
|
1810
|
+
|
1811
|
+
rb_define_method(cTaskScheduler, "comment",
|
1812
|
+
VALUEFUNC(ts_get_comment), 0);
|
1813
|
+
|
1814
|
+
rb_define_method(cTaskScheduler, "comment=",
|
1815
|
+
VALUEFUNC(ts_set_comment), 1);
|
1816
|
+
|
1817
|
+
rb_define_method(cTaskScheduler, "creator",
|
1818
|
+
VALUEFUNC(ts_get_creator), 0);
|
1819
|
+
|
1820
|
+
rb_define_method(cTaskScheduler, "creator=",
|
1821
|
+
VALUEFUNC(ts_set_creator), 1);
|
1822
|
+
|
1823
|
+
rb_define_method(cTaskScheduler, "next_run_time",
|
1824
|
+
VALUEFUNC(ts_get_next_run_time), 0);
|
1825
|
+
|
1826
|
+
rb_define_method(cTaskScheduler, "most_recent_run_time",
|
1827
|
+
VALUEFUNC(ts_get_most_recent_run_time), 0);
|
1828
|
+
|
1829
|
+
rb_define_method(cTaskScheduler, "max_run_time",
|
1830
|
+
VALUEFUNC(ts_get_max_run_time), 0);
|
1831
|
+
|
1832
|
+
rb_define_method(cTaskScheduler, "max_run_time=",
|
1833
|
+
VALUEFUNC(ts_set_max_run_time), 1);
|
1834
|
+
|
1835
|
+
rb_define_alias(cTaskScheduler, "host=", "machine=");
|
1836
|
+
|
1837
|
+
/* 0.1.0: The version of this library, returned as a String */
|
1838
|
+
rb_define_const(cTaskScheduler, "VERSION",
|
1839
|
+
rb_str_new2(WIN32_TASKSCHEDULER_VERSION));
|
1840
|
+
|
1841
|
+
/* 4: Typically used for system monitoring applications */
|
1842
|
+
rb_define_const(cTaskScheduler, "IDLE", INT2FIX(IDLE_PRIORITY_CLASS));
|
1843
|
+
|
1844
|
+
/* 8: The default priority class. Recommended for most applications */
|
1845
|
+
rb_define_const(cTaskScheduler, "NORMAL", INT2FIX(NORMAL_PRIORITY_CLASS));
|
1846
|
+
|
1847
|
+
/* 13: High priority. Use only for applications that need regular focus */
|
1848
|
+
rb_define_const(cTaskScheduler, "HIGH", INT2FIX(HIGH_PRIORITY_CLASS));
|
1849
|
+
|
1850
|
+
/* 24: Extremely high priority. May affect other applications. Not recommended. */
|
1851
|
+
rb_define_const(cTaskScheduler, "REALTIME", INT2FIX(REALTIME_PRIORITY_CLASS));
|
1852
|
+
|
1853
|
+
/* 6: Between the IDLE and NORMAL priority class */
|
1854
|
+
rb_define_const(cTaskScheduler, "BELOW_NORMAL", INT2FIX(BELOW_NORMAL_PRIORITY_CLASS));
|
1855
|
+
|
1856
|
+
/* 10: Between the NORMAL and HIGH priority class */
|
1857
|
+
rb_define_const(cTaskScheduler, "ABOVE_NORMAL", INT2FIX(ABOVE_NORMAL_PRIORITY_CLASS));
|
1858
|
+
|
1859
|
+
/* 0: Trigger is set to run the task a single time */
|
1860
|
+
rb_define_const(cTaskScheduler, "ONCE", INT2FIX(TASK_TIME_TRIGGER_ONCE));
|
1861
|
+
|
1862
|
+
/* 1: Trigger is set to run the task on a daily interval */
|
1863
|
+
rb_define_const(cTaskScheduler, "DAILY", INT2FIX(TASK_TIME_TRIGGER_DAILY));
|
1864
|
+
|
1865
|
+
/* 2: Trigger is set to run the work item on specific days of a specific
|
1866
|
+
* week of a specific month
|
1867
|
+
*/
|
1868
|
+
rb_define_const(cTaskScheduler, "WEEKLY", INT2FIX(TASK_TIME_TRIGGER_WEEKLY));
|
1869
|
+
|
1870
|
+
/* 3: Trigger is set to run the task on a specific day(s) of the month */
|
1871
|
+
rb_define_const(cTaskScheduler, "MONTHLYDATE",
|
1872
|
+
INT2FIX(TASK_TIME_TRIGGER_MONTHLYDATE)
|
1873
|
+
);
|
1874
|
+
|
1875
|
+
/* 4: Trigger is set to run the task on specific days, weeks and months */
|
1876
|
+
rb_define_const(cTaskScheduler, "MONTHLYDOW",
|
1877
|
+
INT2FIX(TASK_TIME_TRIGGER_MONTHLYDOW)
|
1878
|
+
);
|
1879
|
+
|
1880
|
+
/* 5: Trigger is set to run the task if the system remains idle for the amount
|
1881
|
+
* of time specified.
|
1882
|
+
*/
|
1883
|
+
rb_define_const(cTaskScheduler, "ON_IDLE",
|
1884
|
+
INT2FIX(TASK_EVENT_TRIGGER_ON_IDLE));
|
1885
|
+
|
1886
|
+
/* 6: Trigger is set to run the task at system startup */
|
1887
|
+
rb_define_const(cTaskScheduler, "AT_SYSTEMSTART",
|
1888
|
+
INT2FIX(TASK_EVENT_TRIGGER_AT_SYSTEMSTART));
|
1889
|
+
|
1890
|
+
/* 7: Trigger is set to run the task when a user logs on */
|
1891
|
+
rb_define_const(cTaskScheduler, "AT_LOGON",
|
1892
|
+
INT2FIX(TASK_EVENT_TRIGGER_AT_LOGON));
|
1893
|
+
|
1894
|
+
/* The task will run between the 1st and 7th day of the month */
|
1895
|
+
rb_define_const(cTaskScheduler, "FIRST_WEEK", INT2FIX(TASK_FIRST_WEEK));
|
1896
|
+
|
1897
|
+
/* The task will run between the 8th and 14th day of the month */
|
1898
|
+
rb_define_const(cTaskScheduler, "SECOND_WEEK", INT2FIX(TASK_SECOND_WEEK));
|
1899
|
+
|
1900
|
+
/* The task will run between the 15th and 21st day of the month */
|
1901
|
+
rb_define_const(cTaskScheduler, "THIRD_WEEK", INT2FIX(TASK_THIRD_WEEK));
|
1902
|
+
|
1903
|
+
/* The task will run between the 22nd and 28th day of the month */
|
1904
|
+
rb_define_const(cTaskScheduler, "FOURTH_WEEK", INT2FIX(TASK_FOURTH_WEEK));
|
1905
|
+
|
1906
|
+
/* The task will run between the last seven days of the month */
|
1907
|
+
rb_define_const(cTaskScheduler, "LAST_WEEK", INT2FIX(TASK_LAST_WEEK));
|
1908
|
+
|
1909
|
+
/* The task will run on Sunday */
|
1910
|
+
rb_define_const(cTaskScheduler, "SUNDAY", INT2FIX(TASK_SUNDAY));
|
1911
|
+
|
1912
|
+
/* The task will run on Monday */
|
1913
|
+
rb_define_const(cTaskScheduler, "MONDAY", INT2FIX(TASK_MONDAY));
|
1914
|
+
|
1915
|
+
/* The task will run on Tuesday */
|
1916
|
+
rb_define_const(cTaskScheduler, "TUESDAY", INT2FIX(TASK_TUESDAY));
|
1917
|
+
|
1918
|
+
/* The task will run on Wednesday */
|
1919
|
+
rb_define_const(cTaskScheduler, "WEDNESDAY", INT2FIX(TASK_WEDNESDAY));
|
1920
|
+
|
1921
|
+
/* The task will run on Thursday */
|
1922
|
+
rb_define_const(cTaskScheduler, "THURSDAY", INT2FIX(TASK_THURSDAY));
|
1923
|
+
|
1924
|
+
/* The task will run on Friday */
|
1925
|
+
rb_define_const(cTaskScheduler, "FRIDAY", INT2FIX(TASK_FRIDAY));
|
1926
|
+
|
1927
|
+
/* The task will run on Saturday */
|
1928
|
+
rb_define_const(cTaskScheduler, "SATURDAY", INT2FIX(TASK_SATURDAY));
|
1929
|
+
|
1930
|
+
/* The task will run in January */
|
1931
|
+
rb_define_const(cTaskScheduler, "JANUARY", INT2FIX(TASK_JANUARY));
|
1932
|
+
|
1933
|
+
/* The task will run in Februrary */
|
1934
|
+
rb_define_const(cTaskScheduler, "FEBRUARY", INT2FIX(TASK_FEBRUARY));
|
1935
|
+
|
1936
|
+
/* The task will run in March */
|
1937
|
+
rb_define_const(cTaskScheduler, "MARCH", INT2FIX(TASK_MARCH));
|
1938
|
+
|
1939
|
+
/* The task will run in April */
|
1940
|
+
rb_define_const(cTaskScheduler, "APRIL", INT2FIX(TASK_APRIL));
|
1941
|
+
|
1942
|
+
/* The task will run in May */
|
1943
|
+
rb_define_const(cTaskScheduler, "MAY", INT2FIX(TASK_MAY));
|
1944
|
+
|
1945
|
+
/* The task will run in June */
|
1946
|
+
rb_define_const(cTaskScheduler, "JUNE", INT2FIX(TASK_JUNE));
|
1947
|
+
|
1948
|
+
/* The task will run in July */
|
1949
|
+
rb_define_const(cTaskScheduler, "JULY", INT2FIX(TASK_JULY));
|
1950
|
+
|
1951
|
+
/* The task will run in August */
|
1952
|
+
rb_define_const(cTaskScheduler, "AUGUST", INT2FIX(TASK_AUGUST));
|
1953
|
+
|
1954
|
+
/* The task will run in September */
|
1955
|
+
rb_define_const(cTaskScheduler, "SEPTEMBER", INT2FIX(TASK_SEPTEMBER));
|
1956
|
+
|
1957
|
+
/* The task will run in October */
|
1958
|
+
rb_define_const(cTaskScheduler, "OCTOBER", INT2FIX(TASK_OCTOBER));
|
1959
|
+
|
1960
|
+
/* The task will run in November */
|
1961
|
+
rb_define_const(cTaskScheduler, "NOVEMBER", INT2FIX(TASK_NOVEMBER));
|
1962
|
+
|
1963
|
+
/* The task will run in December */
|
1964
|
+
rb_define_const(cTaskScheduler, "DECEMBER", INT2FIX(TASK_DECEMBER));
|
1965
|
+
|
1966
|
+
/* The task must be allowed to interact with the logged-on user */
|
1967
|
+
rb_define_const(cTaskScheduler, "INTERACTIVE", INT2FIX(TASK_FLAG_INTERACTIVE));
|
1968
|
+
|
1969
|
+
/* The task must be deleted when there are no more scheduled run times */
|
1970
|
+
rb_define_const(cTaskScheduler, "DELETE_WHEN_DONE",
|
1971
|
+
INT2FIX(TASK_FLAG_DELETE_WHEN_DONE));
|
1972
|
+
|
1973
|
+
/* The task must be disabled */
|
1974
|
+
rb_define_const(cTaskScheduler, "DISABLED", INT2FIX(TASK_FLAG_DISABLED));
|
1975
|
+
|
1976
|
+
/* The task must only begin if the computer is not in use at the scheduled
|
1977
|
+
* start time.
|
1978
|
+
*/
|
1979
|
+
rb_define_const(cTaskScheduler, "START_ONLY_IF_IDLE",
|
1980
|
+
INT2FIX(TASK_FLAG_START_ONLY_IF_IDLE));
|
1981
|
+
|
1982
|
+
/* The task must be terminated if the computer makes an idle to non-idle
|
1983
|
+
* transition while the task is running.
|
1984
|
+
*/
|
1985
|
+
rb_define_const(cTaskScheduler, "KILL_ON_IDLE_END",
|
1986
|
+
INT2FIX(TASK_FLAG_KILL_ON_IDLE_END));
|
1987
|
+
|
1988
|
+
/* The task must not start if the computer is running on battery power */
|
1989
|
+
rb_define_const(cTaskScheduler, "DONT_START_IF_ON_BATTERIES",
|
1990
|
+
INT2FIX(TASK_FLAG_DONT_START_IF_ON_BATTERIES));
|
1991
|
+
|
1992
|
+
/* The task must end, and the associated application must quit, if the
|
1993
|
+
* computer switches to batter power.
|
1994
|
+
*/
|
1995
|
+
rb_define_const(cTaskScheduler, "KILL_IF_GOING_ON_BATTERIES",
|
1996
|
+
INT2FIX(TASK_FLAG_KILL_IF_GOING_ON_BATTERIES));
|
1997
|
+
|
1998
|
+
/* The task must be hidden */
|
1999
|
+
rb_define_const(cTaskScheduler, "HIDDEN", INT2FIX(TASK_FLAG_HIDDEN));
|
2000
|
+
|
2001
|
+
/* The task must start again if the computer makes a non-idel to idle
|
2002
|
+
* transition before all the task's triggers elapse.
|
2003
|
+
*/
|
2004
|
+
rb_define_const(cTaskScheduler, "RESTART_ON_IDLE_RESUME",
|
2005
|
+
INT2FIX(TASK_FLAG_RESTART_ON_IDLE_RESUME));
|
2006
|
+
|
2007
|
+
/* The task must cause the system to resume or awaken if the system is
|
2008
|
+
* sleeping.
|
2009
|
+
*/
|
2010
|
+
rb_define_const(cTaskScheduler, "SYSTEM_REQUIRED",
|
2011
|
+
INT2FIX(TASK_FLAG_SYSTEM_REQUIRED));
|
2012
|
+
|
2013
|
+
/* Trigger structure's end date is valid. If this flag is not set the end
|
2014
|
+
* date data is ignored and the trigger will be valid indefinitely.
|
2015
|
+
*/
|
2016
|
+
rb_define_const(cTaskScheduler, "FLAG_HAS_END_DATE",
|
2017
|
+
INT2FIX(TASK_TRIGGER_FLAG_HAS_END_DATE));
|
2018
|
+
|
2019
|
+
/* Task will be terminated at the end of the active trigger's lifetime. */
|
2020
|
+
rb_define_const(cTaskScheduler, "FLAG_KILL_AT_DURATION_END",
|
2021
|
+
INT2FIX(TASK_TRIGGER_FLAG_KILL_AT_DURATION_END));
|
2022
|
+
|
2023
|
+
/* Task trigger is inactive */
|
2024
|
+
rb_define_const(cTaskScheduler, "FLAG_DISABLED",
|
2025
|
+
INT2FIX(TASK_TRIGGER_FLAG_DISABLED));
|
2026
|
+
|
2027
|
+
/* The task must run only if the user specified in the task is logged
|
2028
|
+
* on interactively.
|
2029
|
+
*/
|
2030
|
+
rb_define_const(cTaskScheduler, "RUN_ONLY_IF_LOGGED_ON",
|
2031
|
+
INT2FIX(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON));
|
2032
|
+
|
2033
|
+
/* 1440: The maximum number of times a scheduled task can be run per day. */
|
2034
|
+
rb_define_const(cTaskScheduler, "MAX_RUN_TIMES",
|
2035
|
+
INT2FIX(TASK_MAX_RUN_TIMES));
|
2036
|
+
}
|