win32-taskscheduler 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,20 @@
1
+ == 0.2.1 - 8-Oct-2011
2
+ * Fixed a bug that would not allow task to run as SYSTEM. Thanks go to
3
+ Josh cooper for the spot and patch.
4
+ * Fixed a bug in new_work_item that would cause it to crash if you tried
5
+ to create a work item that already existed. An error is now raised instead.
6
+ Thanks go to Pete Higgins for the spot.
7
+ * The set_trigger and trigger= methods now internally transform and validate
8
+ the trigger hash in the same manner as new_work_item. Thanks again go to
9
+ Pete Higgins.
10
+ * Cleaned up the repo. The C source files have been removed from the main
11
+ repository (and this gem). They are in a separate branch on github for
12
+ anyone who misses them.
13
+ * Refactored the Rakefile, removing tasks related to the old C source files,
14
+ and added tasks for cleaning, building and installing a gem.
15
+ * Updated the README file, eliminating references to anything that was only
16
+ related to the older C version.
17
+
1
18
  == 0.2.0 - 19-Jun-2009
2
19
  * Rewritten in pure Ruby!
3
20
  * The TaskScheduler::ONCE constant is now a valid trigger type. Thanks go to
data/README CHANGED
@@ -1,68 +1,76 @@
1
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.
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
4
 
5
- = Synopsis
6
- require 'win32/taskscheduler'
7
- include Win32
8
-
9
- ts = TaskScheduler.new
5
+ = Prerequisites
6
+ * win32-api
7
+ * windows-pr
10
8
 
11
- # Create a trigger that starts on April 25, 2014 at 11:05 pm. The trigger
12
- # will run on the first and last week of the month, on Monday and Friday,
13
- # in the months of April and May.
14
- #
15
- trigger = {
16
- :start_year => 2014,
17
- :start_month => 4,
18
- :start_day => 25,
19
- :start_hour => 23,
20
- :start_minute => 5,
21
- :trigger_type => TaskScheduler::MONTHLYDOW,
22
- :type => {
23
- :weeks => TaskScheduler::FIRST_WEEK | TaskScheduler::LAST_WEEK,
24
- :days_of_week => TaskScheduler::MONDAY | TaskScheduler::FRIDAY,
25
- :months => TaskScheduler::APRIL | TaskScheduler::MAY
26
- }
27
- }
9
+ = Installation
10
+ gem install win32-taskscheduler
28
11
 
29
- ts.new_work_item('foo', trigger)
30
- ts.application_name = 'notepad.exe'
31
- ts.save
12
+ = Synopsis
13
+ require 'win32/taskscheduler'
14
+ include Win32
32
15
 
33
- = Prerequisites
34
- Ruby 1.8.2 or later.
35
- Building from source requires VC++ 6.0 or later.
36
- Windows XP or earlier. Vista and later not currently supported.
16
+ ts = TaskScheduler.new
37
17
 
38
- = Installation
39
- rake install (non-gem) OR rake install_gem (gem)
18
+ # Create a trigger that starts on April 25, 2014 at 11:05 pm. The trigger
19
+ # will run on the first and last week of the month, on Monday and Friday,
20
+ # in the months of April and May.
21
+ #
22
+ trigger = {
23
+ :start_year => 2014,
24
+ :start_month => 4,
25
+ :start_day => 25,
26
+ :start_hour => 23,
27
+ :start_minute => 5,
28
+ :trigger_type => TaskScheduler::MONTHLYDOW,
29
+ :type => {
30
+ :weeks => TaskScheduler::FIRST_WEEK | TaskScheduler::LAST_WEEK,
31
+ :days_of_week => TaskScheduler::MONDAY | TaskScheduler::FRIDAY,
32
+ :months => TaskScheduler::APRIL | TaskScheduler::MAY
33
+ }
34
+ }
40
35
 
41
- For most of you 'gem install win32-taskscheduler' will work.
36
+ ts.new_work_item('my_notepad', trigger)
37
+ ts.application_name = 'notepad.exe'
38
+ ts.save
42
39
 
43
40
  = Documentation
44
- If you installed this library as a gem then the documentation was built for
45
- you and can be viewed if your gem server is running.
41
+ If you installed this library as a gem then the documentation was built for
42
+ you and can be viewed if your gem server is running. There is also some
43
+ documentation on the github wiki page.
46
44
 
47
- Otherwise, you can look at the doc/taskscheduler.txt file which should have
48
- everything you need.
45
+ Otherwise, you can look at the doc/taskscheduler.txt file which should have
46
+ everything you need.
49
47
 
50
48
  = Acknowledgements
51
- This library was modeled to some degree on the Win32::TaskScheduler Perl
52
- module by Umberto Nicoletti. However, there are some differences. Please see
53
- the documentation for details.
49
+ This library was modeled to some degree on the Win32::TaskScheduler Perl
50
+ module by Umberto Nicoletti. However, there are some differences. Please see
51
+ the documentation for details.
52
+
53
+ = Using OLE
54
+ There's an OLE version in the works. Please see the 'ole' branch on github.
55
+
56
+ = Warranty
57
+ This package is provided "as is" and without any express or
58
+ implied warranties, including, without limitation, the implied
59
+ warranties of merchantability and fitness for a particular purpose.
60
+
61
+ = Known Issues
62
+ None known.
63
+
64
+ Please submit any bug reports to the project page at
65
+ http://www.rubyforge.org/projects/win32utils.
54
66
 
55
- = On using OLE + WMI + Win32_ScheduledJob
56
- I will probably include a pure Ruby version of this library at some point,
57
- and you can find what I have so far in CVS under lib/win32. Note, however,
58
- that there are some significant differences in behavior between the C
59
- library and WMI, along with limitations regarding modification to existing
60
- tasks.
67
+ = Copyright
68
+ (C) 2003-2011 Daniel J. Berger
69
+ All Rights Reserved
61
70
 
62
- You can find a list of differences here: http://tinyurl.com/2l3yau
71
+ = License
72
+ Artistic 2.0
63
73
 
64
- = Developer's Notes
65
- The CoInitialize() function is used internally instead of CoInitializeEx()
66
- function intentionally. The CoInitialize() function merely calls the
67
- CoInitializeEx() function with NULL and COINIT_APARTMENTTHREADED arguments,
68
- which is what we would do in any case.
74
+ = Authors
75
+ Park Heesob
76
+ Daniel Berger
data/Rakefile CHANGED
@@ -1,54 +1,34 @@
1
1
  require 'rake'
2
- require 'rake/clean'
3
2
  require 'rake/testtask'
3
+ require 'rake/clean'
4
4
  require 'rbconfig'
5
5
  include Config
6
6
 
7
- =begin
8
- desc "Cleans up the C related files created during the build"
9
- task :clean do
10
- Dir.chdir('ext') do
11
- if File.exists?('taskscheduler.o') || File.exists?('taskscheduler.so')
12
- sh 'nmake distclean'
13
- end
14
-
15
- if File.exists?('win32/taskscheduler.so')
16
- File.delete('win32/taskscheduler.so')
17
- end
18
- end
19
- end
20
-
21
- desc "Builds, but does not install, the win32-taskscheduler library"
22
- task :build => [:clean] do
23
- Dir.chdir('ext') do
24
- ruby 'extconf.rb'
25
- sh 'nmake'
26
- FileUtils.cp('taskscheduler.so', 'win32/taskscheduler.so')
27
- end
28
- end
29
- =end
7
+ CLEAN.include("**/*.gem", "**/*.rbc", ".rbx")
30
8
 
31
- desc "Install the win32-taskscheduler library (non-gem)"
32
- task :install => [:build] do
33
- dir = File.join(Config::CONFIG['sitelibdir'], 'win32')
34
- Dir.mkdir(dir) unless File.exists?(dir)
35
- FileUtils.cp('lib/win32/taskscheduler.rb', dir)
36
- end
9
+ namespace 'gem' do
10
+ desc 'Create the win32-taskscheduler gem'
11
+ task :create => [:clean] do
12
+ spec = eval(IO.read('win32-taskscheduler.gemspec'))
13
+ Gem::Builder.new(spec).build
14
+ end
37
15
 
38
- desc 'Install the win32-taskscheduler library as a gem'
39
- task :install_gem do
40
- ruby 'win32-taskscheduler.gemspec'
41
- file = Dir['win32-taskscheduler*.gem'].first
42
- sh "gem install #{file}"
16
+ desc 'Install the win32-taskscheduler library as a gem'
17
+ task :install => [:create] do
18
+ file = Dir['win32-taskscheduler*.gem'].first
19
+ sh "gem install #{file}"
20
+ end
43
21
  end
44
22
 
45
23
  desc 'Run the example code'
46
24
  task :example do
47
- ruby '-Iib examples/taskscheduler_example.rb'
25
+ ruby '-Iib examples/taskscheduler_example.rb'
48
26
  end
49
27
 
50
- desc "Run the test suite for the win32-taskscheduler library"
28
+ desc 'Run the test suite for the win32-taskscheduler library'
51
29
  Rake::TestTask.new do |t|
52
- t.verbose = true
53
- t.warning = true
30
+ t.verbose = true
31
+ t.warning = true
54
32
  end
33
+
34
+ task :default => :test
@@ -9,1669 +9,1681 @@ include Windows::Process
9
9
  include Windows::Error
10
10
  include Windows::MSVCRT::Buffer
11
11
 
12
+ # The Win32 module serves as a namespace only
12
13
  module Win32
13
- class TaskScheduler
14
-
15
- # The version of the win32-taskscheduler library
16
- VERSION = '0.2.0'
17
-
18
- # The error class raised if any task scheduler specific calls fail.
19
- class Error < StandardError; end
20
-
21
- private
22
-
23
- TASK_TIME_TRIGGER_ONCE = 0
24
- TASK_TIME_TRIGGER_DAILY = 1
25
- TASK_TIME_TRIGGER_WEEKLY = 2
26
- TASK_TIME_TRIGGER_MONTHLYDATE = 3
27
- TASK_TIME_TRIGGER_MONTHLYDOW = 4
28
- TASK_EVENT_TRIGGER_ON_IDLE = 5
29
- TASK_EVENT_TRIGGER_AT_SYSTEMSTART = 6
30
- TASK_EVENT_TRIGGER_AT_LOGON = 7
31
-
32
- TASK_SUNDAY = 0x1
33
- TASK_MONDAY = 0x2
34
- TASK_TUESDAY = 0x4
35
- TASK_WEDNESDAY = 0x8
36
- TASK_THURSDAY = 0x10
37
- TASK_FRIDAY = 0x20
38
- TASK_SATURDAY = 0x40
39
- TASK_FIRST_WEEK = 1
40
- TASK_SECOND_WEEK = 2
41
- TASK_THIRD_WEEK = 3
42
- TASK_FOURTH_WEEK = 4
43
- TASK_LAST_WEEK = 5
44
- TASK_JANUARY = 0x1
45
- TASK_FEBRUARY = 0x2
46
- TASK_MARCH = 0x4
47
- TASK_APRIL = 0x8
48
- TASK_MAY = 0x10
49
- TASK_JUNE = 0x20
50
- TASK_JULY = 0x40
51
- TASK_AUGUST = 0x80
52
- TASK_SEPTEMBER = 0x100
53
- TASK_OCTOBER = 0x200
54
- TASK_NOVEMBER = 0x400
55
- TASK_DECEMBER = 0x800
56
-
57
- TASK_FLAG_INTERACTIVE = 0x1
58
- TASK_FLAG_DELETE_WHEN_DONE = 0x2
59
- TASK_FLAG_DISABLED = 0x4
60
- TASK_FLAG_START_ONLY_IF_IDLE = 0x10
61
- TASK_FLAG_KILL_ON_IDLE_END = 0x20
62
- TASK_FLAG_DONT_START_IF_ON_BATTERIES = 0x40
63
- TASK_FLAG_KILL_IF_GOING_ON_BATTERIES = 0x80
64
- TASK_FLAG_RUN_ONLY_IF_DOCKED = 0x100
65
- TASK_FLAG_HIDDEN = 0x200
66
- TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET = 0x400
67
- TASK_FLAG_RESTART_ON_IDLE_RESUME = 0x800
68
- TASK_FLAG_SYSTEM_REQUIRED = 0x1000
69
- TASK_FLAG_RUN_ONLY_IF_LOGGED_ON = 0x2000
70
- TASK_TRIGGER_FLAG_HAS_END_DATE = 0x1
71
- TASK_TRIGGER_FLAG_KILL_AT_DURATION_END = 0x2
72
- TASK_TRIGGER_FLAG_DISABLED = 0x4
73
-
74
- TASK_MAX_RUN_TIMES = 1440
75
- TASKS_TO_RETRIEVE = 5
76
-
77
- CLSCTX_INPROC_SERVER = 0x1
78
- CLSID_CTask = [0x148BD520,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
79
- CLSID_CTaskScheduler = [0x148BD52A,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
80
- IID_ITaskScheduler = [0x148BD527,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
81
- IID_ITask = [0x148BD524,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
82
- IID_IPersistFile = [0x0000010b,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46].pack('LSSC8')
83
-
84
- public
85
-
86
- # Shorthand constants
87
-
88
- IDLE = IDLE_PRIORITY_CLASS
89
- NORMAL = NORMAL_PRIORITY_CLASS
90
- HIGH = HIGH_PRIORITY_CLASS
91
- REALTIME = REALTIME_PRIORITY_CLASS
92
- BELOW_NORMAL = BELOW_NORMAL_PRIORITY_CLASS
93
- ABOVE_NORMAL = ABOVE_NORMAL_PRIORITY_CLASS
94
-
95
- ONCE = TASK_TIME_TRIGGER_ONCE
96
- DAILY = TASK_TIME_TRIGGER_DAILY
97
- WEEKLY = TASK_TIME_TRIGGER_WEEKLY
98
- MONTHLYDATE = TASK_TIME_TRIGGER_MONTHLYDATE
99
- MONTHLYDOW = TASK_TIME_TRIGGER_MONTHLYDOW
100
-
101
- ON_IDLE = TASK_EVENT_TRIGGER_ON_IDLE
102
- AT_SYSTEMSTART = TASK_EVENT_TRIGGER_AT_SYSTEMSTART
103
- AT_LOGON = TASK_EVENT_TRIGGER_AT_LOGON
104
- FIRST_WEEK = TASK_FIRST_WEEK
105
- SECOND_WEEK = TASK_SECOND_WEEK
106
- THIRD_WEEK = TASK_THIRD_WEEK
107
- FOURTH_WEEK = TASK_FOURTH_WEEK
108
- LAST_WEEK = TASK_LAST_WEEK
109
- SUNDAY = TASK_SUNDAY
110
- MONDAY = TASK_MONDAY
111
- TUESDAY = TASK_TUESDAY
112
- WEDNESDAY = TASK_WEDNESDAY
113
- THURSDAY = TASK_THURSDAY
114
- FRIDAY = TASK_FRIDAY
115
- SATURDAY = TASK_SATURDAY
116
- JANUARY = TASK_JANUARY
117
- FEBRUARY = TASK_FEBRUARY
118
- MARCH = TASK_MARCH
119
- APRIL = TASK_APRIL
120
- MAY = TASK_MAY
121
- JUNE = TASK_JUNE
122
- JULY = TASK_JULY
123
- AUGUST = TASK_AUGUST
124
- SEPTEMBER = TASK_SEPTEMBER
125
- OCTOBER = TASK_OCTOBER
126
- NOVEMBER = TASK_NOVEMBER
127
- DECEMBER = TASK_DECEMBER
128
-
129
- INTERACTIVE = TASK_FLAG_INTERACTIVE
130
- DELETE_WHEN_DONE = TASK_FLAG_DELETE_WHEN_DONE
131
- DISABLED = TASK_FLAG_DISABLED
132
- START_ONLY_IF_IDLE = TASK_FLAG_START_ONLY_IF_IDLE
133
- KILL_ON_IDLE_END = TASK_FLAG_KILL_ON_IDLE_END
134
- DONT_START_IF_ON_BATTERIES = TASK_FLAG_DONT_START_IF_ON_BATTERIES
135
- KILL_IF_GOING_ON_BATTERIES = TASK_FLAG_KILL_IF_GOING_ON_BATTERIES
136
- RUN_ONLY_IF_DOCKED = TASK_FLAG_RUN_ONLY_IF_DOCKED
137
- HIDDEN = TASK_FLAG_HIDDEN
138
- RUN_IF_CONNECTED_TO_INTERNET = TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET
139
- RESTART_ON_IDLE_RESUME = TASK_FLAG_RESTART_ON_IDLE_RESUME
140
- SYSTEM_REQUIRED = TASK_FLAG_SYSTEM_REQUIRED
141
- RUN_ONLY_IF_LOGGED_ON = TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
142
-
143
- FLAG_HAS_END_DATE = TASK_TRIGGER_FLAG_HAS_END_DATE
144
- FLAG_KILL_AT_DURATION_END = TASK_TRIGGER_FLAG_KILL_AT_DURATION_END
145
- FLAG_DISABLED = TASK_TRIGGER_FLAG_DISABLED
146
-
147
- MAX_RUN_TIMES = TASK_MAX_RUN_TIMES
148
-
149
- # Returns a new TaskScheduler object. If a work_item (and possibly the
150
- # the trigger) are passed as arguments then a new work item is created and
151
- # associated with that trigger, although you can still activate other tasks
152
- # with the same handle.
153
- #
154
- # This is really just a bit of convenience. Passing arguments to the
155
- # constructor is the same as calling TaskScheduler.new plus
156
- # TaskScheduler#new_work_item.
157
- #
158
- def initialize(work_item=nil, trigger=nil)
159
- @pITS = nil
160
- @pITask = nil
161
-
162
- hr = CoInitialize(0)
163
-
164
- if SUCCEEDED(hr)
165
- ptr = 0.chr * 4
166
-
167
- hr = CoCreateInstance(
168
- CLSID_CTaskScheduler,
169
- nil,
170
- CLSCTX_INPROC_SERVER,
171
- IID_ITaskScheduler,
172
- ptr
173
- )
174
-
175
- if FAILED(hr)
176
- raise Error, get_last_error
177
- end
178
-
179
- @pITS = ptr.unpack('L').first
180
- else
181
- raise Error, get_last_error
182
- end
183
-
184
- if work_item
185
- if trigger
186
- raise TypeError unless trigger.is_a?(Hash)
187
- new_work_item(work_item, trigger)
188
- end
189
- end
190
-
191
- self
14
+ # The TaskScheduler class encapsulates taskscheduler settings and behavior
15
+ class TaskScheduler
16
+
17
+ # The version of the win32-taskscheduler library
18
+ VERSION = '0.2.1'
19
+
20
+ # The error class raised if any task scheduler specific calls fail.
21
+ class Error < StandardError; end
22
+
23
+ private
24
+
25
+ # :stopdoc:
26
+
27
+ TASK_TIME_TRIGGER_ONCE = 0
28
+ TASK_TIME_TRIGGER_DAILY = 1
29
+ TASK_TIME_TRIGGER_WEEKLY = 2
30
+ TASK_TIME_TRIGGER_MONTHLYDATE = 3
31
+ TASK_TIME_TRIGGER_MONTHLYDOW = 4
32
+ TASK_EVENT_TRIGGER_ON_IDLE = 5
33
+ TASK_EVENT_TRIGGER_AT_SYSTEMSTART = 6
34
+ TASK_EVENT_TRIGGER_AT_LOGON = 7
35
+
36
+ TASK_SUNDAY = 0x1
37
+ TASK_MONDAY = 0x2
38
+ TASK_TUESDAY = 0x4
39
+ TASK_WEDNESDAY = 0x8
40
+ TASK_THURSDAY = 0x10
41
+ TASK_FRIDAY = 0x20
42
+ TASK_SATURDAY = 0x40
43
+ TASK_FIRST_WEEK = 1
44
+ TASK_SECOND_WEEK = 2
45
+ TASK_THIRD_WEEK = 3
46
+ TASK_FOURTH_WEEK = 4
47
+ TASK_LAST_WEEK = 5
48
+ TASK_JANUARY = 0x1
49
+ TASK_FEBRUARY = 0x2
50
+ TASK_MARCH = 0x4
51
+ TASK_APRIL = 0x8
52
+ TASK_MAY = 0x10
53
+ TASK_JUNE = 0x20
54
+ TASK_JULY = 0x40
55
+ TASK_AUGUST = 0x80
56
+ TASK_SEPTEMBER = 0x100
57
+ TASK_OCTOBER = 0x200
58
+ TASK_NOVEMBER = 0x400
59
+ TASK_DECEMBER = 0x800
60
+
61
+ TASK_FLAG_INTERACTIVE = 0x1
62
+ TASK_FLAG_DELETE_WHEN_DONE = 0x2
63
+ TASK_FLAG_DISABLED = 0x4
64
+ TASK_FLAG_START_ONLY_IF_IDLE = 0x10
65
+ TASK_FLAG_KILL_ON_IDLE_END = 0x20
66
+ TASK_FLAG_DONT_START_IF_ON_BATTERIES = 0x40
67
+ TASK_FLAG_KILL_IF_GOING_ON_BATTERIES = 0x80
68
+ TASK_FLAG_RUN_ONLY_IF_DOCKED = 0x100
69
+ TASK_FLAG_HIDDEN = 0x200
70
+ TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET = 0x400
71
+ TASK_FLAG_RESTART_ON_IDLE_RESUME = 0x800
72
+ TASK_FLAG_SYSTEM_REQUIRED = 0x1000
73
+ TASK_FLAG_RUN_ONLY_IF_LOGGED_ON = 0x2000
74
+ TASK_TRIGGER_FLAG_HAS_END_DATE = 0x1
75
+ TASK_TRIGGER_FLAG_KILL_AT_DURATION_END = 0x2
76
+ TASK_TRIGGER_FLAG_DISABLED = 0x4
77
+
78
+ TASK_MAX_RUN_TIMES = 1440
79
+ TASKS_TO_RETRIEVE = 5
80
+
81
+ # COM
82
+
83
+ CLSCTX_INPROC_SERVER = 0x1
84
+ CLSID_CTask = [0x148BD520,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
85
+ CLSID_CTaskScheduler = [0x148BD52A,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
86
+ IID_ITaskScheduler = [0x148BD527,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
87
+ IID_ITask = [0x148BD524,0xA2AB,0x11CE,0xB1,0x1F,0x00,0xAA,0x00,0x53,0x05,0x03].pack('LSSC8')
88
+ IID_IPersistFile = [0x0000010b,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46].pack('LSSC8')
89
+
90
+ public
91
+
92
+ # :startdoc:
93
+
94
+ # Shorthand constants
95
+
96
+ IDLE = IDLE_PRIORITY_CLASS
97
+ NORMAL = NORMAL_PRIORITY_CLASS
98
+ HIGH = HIGH_PRIORITY_CLASS
99
+ REALTIME = REALTIME_PRIORITY_CLASS
100
+ BELOW_NORMAL = BELOW_NORMAL_PRIORITY_CLASS
101
+ ABOVE_NORMAL = 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
+ # Returns a new TaskScheduler object. If a work_item (and possibly the
158
+ # the trigger) are passed as arguments then a new work item is created and
159
+ # associated with that trigger, although you can still activate other tasks
160
+ # with the same handle.
161
+ #
162
+ # This is really just a bit of convenience. Passing arguments to the
163
+ # constructor is the same as calling TaskScheduler.new plus
164
+ # TaskScheduler#new_work_item.
165
+ #
166
+ def initialize(work_item=nil, trigger=nil)
167
+ @pITS = nil
168
+ @pITask = nil
169
+
170
+ hr = CoInitialize(0)
171
+
172
+ if SUCCEEDED(hr)
173
+ ptr = 0.chr * 4
174
+
175
+ hr = CoCreateInstance(
176
+ CLSID_CTaskScheduler,
177
+ nil,
178
+ CLSCTX_INPROC_SERVER,
179
+ IID_ITaskScheduler,
180
+ ptr
181
+ )
182
+
183
+ if FAILED(hr)
184
+ raise Error, get_last_error
185
+ end
186
+
187
+ @pITS = ptr.unpack('L').first
188
+ else
189
+ raise Error, get_last_error
192
190
  end
193
191
 
194
- # Returns an array of scheduled task names.
195
- #
196
- def enum
197
- raise Error, 'null pointer' if @pITS.nil?
198
-
199
- lpVtbl = 0.chr * 4
200
- table = 0.chr * 24
192
+ if work_item
193
+ if trigger
194
+ raise TypeError unless trigger.is_a?(Hash)
195
+ new_work_item(work_item, trigger)
196
+ end
197
+ end
198
+ end
201
199
 
202
- memcpy(lpVtbl, @pITS, 4)
203
- memcpy(table, lpVtbl.unpack('L').first, 24)
204
- table = table.unpack('L*')
200
+ # Returns an array of scheduled task names.
201
+ #
202
+ def enum
203
+ raise Error, 'null pointer' if @pITS.nil?
205
204
 
206
- enum = Win32::API::Function.new(table[5], 'PP', 'L')
205
+ lpVtbl = 0.chr * 4
206
+ table = 0.chr * 24
207
207
 
208
- ptr = 0.chr * 4
209
- hr = enum.call(@pITS, ptr)
208
+ memcpy(lpVtbl, @pITS, 4)
209
+ memcpy(table, lpVtbl.unpack('L').first, 24)
210
+ table = table.unpack('L*')
210
211
 
211
- raise Error, get_last_error if hr != S_OK
212
+ enum = Win32::API::Function.new(table[5], 'PP', 'L')
212
213
 
213
- pIEnum = ptr.unpack('L').first
214
- lpVtbl = 0.chr * 4
215
- table = 0.chr * 16
214
+ ptr = 0.chr * 4
215
+ hr = enum.call(@pITS, ptr)
216
216
 
217
- memcpy(lpVtbl, pIEnum, 4)
218
- memcpy(table, lpVtbl.unpack('L').first, 16)
219
- table = table.unpack('L*')
217
+ raise Error, get_last_error if hr != S_OK
220
218
 
221
- _next = Win32::API::Function.new(table[3], 'PLPP', 'L')
222
- release = Win32::API::Function.new(table[2], 'P', 'L')
219
+ pIEnum = ptr.unpack('L').first
220
+ lpVtbl = 0.chr * 4
221
+ table = 0.chr * 16
223
222
 
224
- array = []
225
- fetched_tasks = 0.chr * 4
226
- pnames = 0.chr * 4
223
+ memcpy(lpVtbl, pIEnum, 4)
224
+ memcpy(table, lpVtbl.unpack('L').first, 16)
225
+ table = table.unpack('L*')
227
226
 
228
- while (_next.call(pIEnum, TASKS_TO_RETRIEVE, pnames, fetched_tasks) >= S_OK) &&
229
- (fetched_tasks.unpack('L').first != 0)
227
+ _next = Win32::API::Function.new(table[3], 'PLPP', 'L')
228
+ release = Win32::API::Function.new(table[2], 'P', 'L')
230
229
 
231
- tasks = fetched_tasks.unpack('L').first
232
- names = 0.chr * 4 * tasks
233
- memcpy(names, pnames.unpack('L').first, 4 * tasks)
230
+ array = []
231
+ fetched_tasks = 0.chr * 4
232
+ pnames = 0.chr * 4
234
233
 
235
- for i in 0 ... tasks
236
- str = 0.chr * 256
237
- wcscpy(str, names[i*4, 4].unpack('L').first)
238
- array.push(wide_to_multi(str))
239
- CoTaskMemFree(names[i*4, 4].unpack('L').first)
240
- end
234
+ while (_next.call(pIEnum, TASKS_TO_RETRIEVE, pnames, fetched_tasks) >= S_OK) &&
235
+ (fetched_tasks.unpack('L').first != 0)
241
236
 
242
- CoTaskMemFree(pnames.unpack('L').first)
243
- end
237
+ tasks = fetched_tasks.unpack('L').first
238
+ names = 0.chr * 4 * tasks
239
+ memcpy(names, pnames.unpack('L').first, 4 * tasks)
244
240
 
245
- release.call(pIEnum)
241
+ for i in 0 ... tasks
242
+ str = 0.chr * 256
243
+ wcscpy(str, names[i*4, 4].unpack('L').first)
244
+ array.push(wide_to_multi(str))
245
+ CoTaskMemFree(names[i*4, 4].unpack('L').first)
246
+ end
246
247
 
247
- array
248
+ CoTaskMemFree(pnames.unpack('L').first)
248
249
  end
249
-
250
- alias :tasks :enum
251
250
 
252
- # Activate the specified task.
253
- #
254
- def activate(task)
255
- raise Error, 'null pointer' if @pITS.nil?
256
- raise TypeError unless task.is_a?(String)
251
+ release.call(pIEnum)
252
+
253
+ array
254
+ end
257
255
 
258
- task = multi_to_wide(task)
256
+ alias :tasks :enum
259
257
 
260
- lpVtbl = 0.chr * 4
261
- table = 0.chr * 28
258
+ # Activate the specified task.
259
+ #
260
+ def activate(task)
261
+ raise Error, 'null pointer' if @pITS.nil?
262
+ raise TypeError unless task.is_a?(String)
262
263
 
263
- memcpy(lpVtbl, @pITS, 4)
264
- memcpy(table, lpVtbl.unpack('L').first, 28)
265
- table = table.unpack('L*')
264
+ task = multi_to_wide(task)
266
265
 
267
- activate = Win32::API::Function.new(table[6], 'PPPP', 'L')
266
+ lpVtbl = 0.chr * 4
267
+ table = 0.chr * 28
268
268
 
269
- ptr = 0.chr * 4
270
- hr = activate.call(@pITS, task, IID_ITask, ptr)
269
+ memcpy(lpVtbl, @pITS, 4)
270
+ memcpy(table, lpVtbl.unpack('L').first, 28)
271
+ table = table.unpack('L*')
271
272
 
272
- if hr != S_OK
273
- raise Error, get_last_error
274
- end
273
+ activate = Win32::API::Function.new(table[6], 'PPPP', 'L')
275
274
 
276
- @pITask = ptr.unpack('L').first
275
+ ptr = 0.chr * 4
276
+ hr = activate.call(@pITS, task, IID_ITask, ptr)
277
277
 
278
- self
278
+ if hr != S_OK
279
+ raise Error, get_last_error
279
280
  end
280
281
 
281
- # Delete the specified task name.
282
- #
283
- def delete(task)
284
- raise Error, 'null pointer' if @pITS.nil?
285
- raise TypeError unless task.is_a?(String)
282
+ @pITask = ptr.unpack('L').first
283
+ end
286
284
 
287
- task = multi_to_wide(task)
285
+ # Delete the specified task name.
286
+ #
287
+ def delete(task)
288
+ raise Error, 'null pointer' if @pITS.nil?
289
+ raise TypeError unless task.is_a?(String)
288
290
 
289
- lpVtbl = 0.chr * 4
290
- table = 0.chr * 32
291
+ task = multi_to_wide(task)
291
292
 
292
- memcpy(lpVtbl, @pITS, 4)
293
- memcpy(table, lpVtbl.unpack('L').first, 32)
294
- table = table.unpack('L*')
293
+ lpVtbl = 0.chr * 4
294
+ table = 0.chr * 32
295
295
 
296
- delete = Win32::API::Function.new(table[7], 'PP', 'L')
296
+ memcpy(lpVtbl, @pITS, 4)
297
+ memcpy(table, lpVtbl.unpack('L').first, 32)
298
+ table = table.unpack('L*')
297
299
 
298
- hr = delete.call(@pITS,task)
300
+ delete = Win32::API::Function.new(table[7], 'PP', 'L')
299
301
 
300
- if hr != S_OK
301
- raise Error, get_last_error
302
- end
302
+ hr = delete.call(@pITS,task)
303
303
 
304
- self
304
+ if hr != S_OK
305
+ raise Error, get_last_error
305
306
  end
307
+ end
306
308
 
307
- # Execute the current task.
308
- #
309
- def run
310
- raise Error, 'null pointer' if @pITask.nil?
309
+ # Execute the current task.
310
+ #
311
+ def run
312
+ raise Error, 'null pointer' if @pITask.nil?
311
313
 
312
- lpVtbl = 0.chr * 4
313
- table = 0.chr * 52
314
+ lpVtbl = 0.chr * 4
315
+ table = 0.chr * 52
314
316
 
315
- memcpy(lpVtbl, @pITask, 4)
316
- memcpy(table, lpVtbl.unpack('L').first, 52)
317
- table = table.unpack('L*')
317
+ memcpy(lpVtbl, @pITask, 4)
318
+ memcpy(table, lpVtbl.unpack('L').first, 52)
319
+ table = table.unpack('L*')
318
320
 
319
- run = Win32::API::Function.new(table[12], 'P', 'L')
321
+ run = Win32::API::Function.new(table[12], 'P', 'L')
320
322
 
321
- hr = run.call(@pITask)
323
+ hr = run.call(@pITask)
322
324
 
323
- if hr != S_OK
324
- raise Error,get_last_error
325
- end
326
-
327
- self
325
+ if hr != S_OK
326
+ raise Error,get_last_error
328
327
  end
328
+ end
329
+
330
+ # Saves the current task. Tasks must be saved before they can be activated.
331
+ # The .job file itself is typically stored in the C:\WINDOWS\Tasks folder.
332
+ #
333
+ # If +file+ (an absolute path) is specified then the job is saved to that
334
+ # file instead. A '.job' extension is recommended but not enforced.
335
+ #
336
+ # Note that calling TaskScheduler#save also resets the TaskScheduler object
337
+ # so that there is no currently active task.
338
+ #
339
+ def save(file = nil)
340
+ raise Error, 'null pointer' if @pITask.nil?
341
+ file = multi_to_wide(file) if file
342
+
343
+ lpVtbl = 0.chr * 4
344
+ table = 0.chr * 12
329
345
 
330
- # Saves the current task. Tasks must be saved before they can be activated.
331
- # The .job file itself is typically stored in the C:\WINDOWS\Tasks folder.
332
- #
333
- # If +file+ (an absolute path) is specified then the job is saved to that
334
- # file instead. A '.job' extension is recommended but not enforced.
335
- #
336
- # Note that calling TaskScheduler#save also resets the TaskScheduler object
337
- # so that there is no currently active task.
338
- #
339
- def save(file = nil)
340
- raise Error, 'null pointer' if @pITask.nil?
341
- file = multi_to_wide(file) if file
346
+ memcpy(lpVtbl, @pITask, 4)
347
+ memcpy(table, lpVtbl.unpack('L').first, 12)
348
+ table = table.unpack('L*')
342
349
 
343
- lpVtbl = 0.chr * 4
344
- table = 0.chr * 12
350
+ queryinterface = Win32::API::Function.new(table[0],'PPP','L')
351
+ release = Win32::API::Function.new(table[2],'P','L')
345
352
 
346
- memcpy(lpVtbl, @pITask, 4)
347
- memcpy(table, lpVtbl.unpack('L').first, 12)
348
- table = table.unpack('L*')
353
+ ptr = 0.chr * 4
349
354
 
350
- queryinterface = Win32::API::Function.new(table[0],'PPP','L')
351
- release = Win32::API::Function.new(table[2],'P','L')
355
+ hr = queryinterface.call(@pITask, IID_IPersistFile, ptr)
352
356
 
353
- ptr = 0.chr * 4
357
+ if hr != S_OK
358
+ raise Error, get_last_error
359
+ end
360
+
361
+ pIPersistFile = ptr.unpack('L').first
362
+
363
+ lpVtbl = 0.chr * 4
364
+ table = 0.chr * 28
354
365
 
355
- hr = queryinterface.call(@pITask, IID_IPersistFile, ptr)
366
+ memcpy(lpVtbl, pIPersistFile,4)
367
+ memcpy(table, lpVtbl.unpack('L').first, 28)
368
+ table = table.unpack('L*')
356
369
 
357
- if hr != S_OK
358
- raise Error, get_last_error
359
- end
370
+ save = Win32::API::Function.new(table[6],'PPL','L')
371
+ release = Win32::API::Function.new(table[2],'P','L')
360
372
 
361
- pIPersistFile = ptr.unpack('L').first
373
+ hr = save.call(pIPersistFile,file,1)
362
374
 
363
- lpVtbl = 0.chr * 4
364
- table = 0.chr * 28
375
+ if hr != S_OK
376
+ raise Error,get_last_error
377
+ end
365
378
 
366
- memcpy(lpVtbl, pIPersistFile,4)
367
- memcpy(table, lpVtbl.unpack('L').first, 28)
368
- table = table.unpack('L*')
379
+ release.call(pIPersistFile)
369
380
 
370
- save = Win32::API::Function.new(table[6],'PPL','L')
371
- release = Win32::API::Function.new(table[2],'P','L')
381
+ CoUninitialize()
382
+ hr = CoInitialize(nil)
372
383
 
373
- hr = save.call(pIPersistFile,file,1)
384
+ if hr >= 0
385
+ ptr = 0.chr * 4
374
386
 
375
- if hr != S_OK
376
- raise Error,get_last_error
377
- end
387
+ hr = CoCreateInstance(
388
+ CLSID_CTaskScheduler,
389
+ nil,
390
+ CLSCTX_INPROC_SERVER,
391
+ IID_ITaskScheduler,
392
+ ptr
393
+ )
378
394
 
379
- release.call(pIPersistFile)
395
+ if hr != S_OK
396
+ CoUninitialize()
397
+ raise Error, get_last_error
398
+ end
380
399
 
381
- CoUninitialize()
382
- hr = CoInitialize(nil)
400
+ @pITS = ptr.unpack('L').first
401
+ else
402
+ raise Error,get_last_error
403
+ end
383
404
 
384
- if hr >= 0
385
- ptr = 0.chr * 4
405
+ release.call(@pITask)
406
+ @pITask = nil
407
+ end
386
408
 
387
- hr = CoCreateInstance(
388
- CLSID_CTaskScheduler,
389
- nil,
390
- CLSCTX_INPROC_SERVER,
391
- IID_ITaskScheduler,
392
- ptr
393
- )
409
+ # Terminate the current task.
410
+ #
411
+ def terminate
412
+ raise Error, 'null pointer' if @pITask.nil?
394
413
 
395
- if hr != S_OK
396
- CoUninitialize()
397
- raise Error, get_last_error
398
- end
414
+ lpVtbl = 0.chr * 4
415
+ table = 0.chr * 56
399
416
 
400
- @pITS = ptr.unpack('L').first
401
- else
402
- raise Error,get_last_error
403
- end
417
+ memcpy(lpVtbl,@pITask,4)
418
+ memcpy(table,lpVtbl.unpack('L').first,56)
419
+ table = table.unpack('L*')
404
420
 
405
- release.call(@pITask)
406
- @pITask = nil
421
+ teriminate = Win32::API::Function.new(table[13],'P','L')
422
+ hr = teriminate.call(@pITask)
407
423
 
408
- self
424
+ if hr != S_OK
425
+ raise Error,get_last_error
409
426
  end
427
+ end
410
428
 
411
- # Terminate the current task.
412
- #
413
- def terminate
414
- raise Error, 'null pointer' if @pITask.nil?
429
+ # Set the host on which the various TaskScheduler methods will execute.
430
+ #
431
+ def machine=(host)
432
+ raise Error, 'null pointer' if @pITS.nil?
433
+ raise TypeError unless host.is_a?(String)
415
434
 
416
- lpVtbl = 0.chr * 4
417
- table = 0.chr * 56
435
+ host_w = multi_to_wide(host)
418
436
 
419
- memcpy(lpVtbl,@pITask,4)
420
- memcpy(table,lpVtbl.unpack('L').first,56)
421
- table = table.unpack('L*')
437
+ lpVtbl = 0.chr * 4
438
+ table = 0.chr * 16
422
439
 
423
- teriminate = Win32::API::Function.new(table[13],'P','L')
424
- hr = teriminate.call(@pITask)
440
+ memcpy(lpVtbl, @pITS, 4)
441
+ memcpy(table, lpVtbl.unpack('L').first, 16)
442
+ table = table.unpack('L*')
425
443
 
426
- if hr != S_OK
427
- raise Error,get_last_error
428
- end
444
+ setTargetComputer = Win32::API::Function.new(table[3], 'PP', 'L')
429
445
 
430
- self
446
+ hr = setTargetComputer.call(@pITS, host_w)
447
+
448
+ if hr != S_OK
449
+ raise Error, get_last_error
450
+ end
451
+
452
+ host
453
+ end
454
+
455
+ alias :host= :machine=
456
+
457
+ # Sets the +user+ and +password+ for the given task. If the user and
458
+ # password are set properly then true is returned.
459
+ #
460
+ # In some cases the job may be created, but the account information was
461
+ # bad. In this case the task is created but a warning is generated and
462
+ # false is returned.
463
+ #
464
+ def set_account_information(user, password)
465
+ raise Error, 'null pointer' if @pITS.nil?
466
+ raise Error, 'No currently active task' if @pITask.nil?
467
+
468
+ lpVtbl = 0.chr * 4
469
+ table = 0.chr * 124
470
+
471
+ memcpy(lpVtbl, @pITask, 4)
472
+ memcpy(table, lpVtbl.unpack('L').first, 124)
473
+ table = table.unpack('L*')
474
+
475
+ setAccountInformation = Win32::API::Function.new(table[30],'PPP','L')
476
+
477
+ if (user.nil? || user=="") && (password.nil? || password=="")
478
+ hr = setAccountInformation.call(@pITask, multi_to_wide(""), nil)
479
+ else
480
+ user = multi_to_wide(user)
481
+ password = multi_to_wide(password)
482
+ hr = setAccountInformation.call(@pITask, user, password)
431
483
  end
432
484
 
433
- # Set the host on which the various TaskScheduler methods will execute.
434
- #
435
- def machine=(host)
436
- raise Error, 'null pointer' if @pITS.nil?
437
- raise TypeError unless host.is_a?(String)
485
+ bool = true
486
+
487
+ case hr
488
+ when S_OK
489
+ return true
490
+ when 0x80070005 # E_ACCESSDENIED
491
+ raise Error, 'access denied'
492
+ when 0x80070057 # E_INVALIDARG
493
+ raise Error, 'invalid argument'
494
+ when 0x8007000E # E_OUTOFMEMORY
495
+ raise Error, 'out of memory'
496
+ when 0x80041312 # SCHED_E_NO_SECURITY_SERVICES
497
+ raise Error, 'no security services on this platform'
498
+ when 0x80041314 # SCHED_E_UNSUPPORTED_ACCOUNT_OPTION
499
+ raise Error, 'unsupported account option'
500
+ when 0x8004130F # SCHED_E_ACCOUNT_INFORMATION_NOT_SET
501
+ warn 'job created, but password was invalid'
502
+ bool = false
503
+ else
504
+ raise Error, 'unknown error'
505
+ end
506
+ bool
507
+ end
508
+
509
+ # Returns the user associated with the task or nil if no user has yet
510
+ # been associated with the task.
511
+ #
512
+ def account_information
513
+ raise Error, 'null pointer' if @pITS.nil?
514
+ raise Error, 'No currently active task' if @pITask.nil?
515
+
516
+ lpVtbl = 0.chr * 4
517
+ table = 0.chr * 128
518
+
519
+ memcpy(lpVtbl, @pITask, 4)
520
+ memcpy(table,lpVtbl.unpack('L').first, 128)
521
+ table = table.unpack('L*')
522
+
523
+ getAccountInformation = Win32::API::Function.new(table[31], 'PP', 'L')
524
+
525
+ ptr = 0.chr * 4
526
+ hr = getAccountInformation.call(@pITask, ptr)
527
+
528
+ if hr == 0x8004130F # SCHED_E_ACCOUNT_INFORMATION_NOT_SET
529
+ user = nil
530
+ elsif hr >= 0 && hr != 0x80041312 # SCHED_E_NO_SECURITY_SERVICES
531
+ str = 0.chr * 256
532
+ wcscpy(str, ptr.unpack('L').first)
533
+ CoTaskMemFree(ptr.unpack('L').first)
534
+ user = wide_to_multi(str)
535
+ else
536
+ CoTaskMemFree(p.unpack('L').first)
537
+ raise Error,get_last_error(hr)
538
+ end
438
539
 
439
- host_w = multi_to_wide(host)
540
+ user
541
+ end
440
542
 
441
- lpVtbl = 0.chr * 4
442
- table = 0.chr * 16
543
+ # Returns the name of the application associated with the task.
544
+ #
545
+ def application_name
546
+ raise Error, 'null pointer' if @pITS.nil?
547
+ raise Error, 'No currently active task' if @pITask.nil?
443
548
 
444
- memcpy(lpVtbl, @pITS, 4)
445
- memcpy(table, lpVtbl.unpack('L').first, 16)
446
- table = table.unpack('L*')
549
+ lpVtbl = 0.chr * 4
550
+ table = 0.chr * 136
447
551
 
448
- setTargetComputer = Win32::API::Function.new(table[3], 'PP', 'L')
552
+ memcpy(lpVtbl, @pITask,4)
553
+ memcpy(table, lpVtbl.unpack('L').first, 136)
554
+ table = table.unpack('L*')
449
555
 
450
- hr = setTargetComputer.call(@pITS, host_w)
556
+ getApplicationName = Win32::API::Function.new(table[33],'PP','L')
451
557
 
452
- if hr != S_OK
453
- raise Error, get_last_error
454
- end
558
+ ptr = 0.chr * 4
559
+ hr = getApplicationName.call(@pITask, ptr)
455
560
 
456
- host
561
+ if hr >= S_OK
562
+ str = 0.chr * 256
563
+ wcscpy(str, ptr.unpack('L').first)
564
+ app = wide_to_multi(str)
565
+ CoTaskMemFree(ptr.unpack('L').first)
566
+ else
567
+ raise Error, get_last_error
457
568
  end
458
569
 
459
- alias :host= :machine=
460
-
461
- # Sets the +user+ and +password+ for the given task. If the user and
462
- # password are set properly then true is returned.
463
- #
464
- # In some cases the job may be created, but the account information was
465
- # bad. In this case the task is created but a warning is generated and
466
- # false is returned.
467
- #
468
- def set_account_information(user, password)
469
- raise Error, 'null pointer' if @pITS.nil?
470
- raise Error, 'No currently active task' if @pITask.nil?
471
-
472
- lpVtbl = 0.chr * 4
473
- table = 0.chr * 124
474
-
475
- memcpy(lpVtbl, @pITask, 4)
476
- memcpy(table, lpVtbl.unpack('L').first, 124)
477
- table = table.unpack('L*')
478
-
479
- setAccountInformation = Win32::API::Function.new(table[30],'PPP','L')
480
-
481
- if (user.nil? || user=="") && (password.nil? || password=="")
482
- hr = setAccountInformation.call(@pITask, "", nil)
483
- else
484
- user = multi_to_wide(user)
485
- password = multi_to_wide(password)
486
- hr = setAccountInformation.call(@pITask, user, password)
487
- end
488
-
489
- bool = true
490
-
491
- case hr
492
- when S_OK
493
- return true
494
- when 0x80070005 # E_ACCESSDENIED
495
- raise Error, 'access denied'
496
- when 0x80070057 # E_INVALIDARG
497
- raise Error, 'invalid argument'
498
- when 0x8007000E # E_OUTOFMEMORY
499
- raise Error, 'out of memory'
500
- when 0x80041312 # SCHED_E_NO_SECURITY_SERVICES
501
- raise Error, 'no security services on this platform'
502
- when 0x80041314 # SCHED_E_UNSUPPORTED_ACCOUNT_OPTION
503
- raise Error, 'unsupported account option'
504
- when 0x8004130F # SCHED_E_ACCOUNT_INFORMATION_NOT_SET
505
- warn 'job created, but password was invalid'
506
- bool = false
507
- else
508
- raise Error, 'unknown error'
509
- end
510
- bool
570
+ app
571
+ end
572
+
573
+ # Sets the application name associated with the task.
574
+ #
575
+ def application_name=(app)
576
+ raise Error, 'null pointer' if @pITS.nil?
577
+ raise Error, 'No currently active task' if @pITask.nil?
578
+ raise TypeError unless app.is_a?(String)
579
+
580
+ app_w = multi_to_wide(app)
581
+
582
+ lpVtbl = 0.chr * 4
583
+ table = 0.chr * 132
584
+ memcpy(lpVtbl,@pITask,4)
585
+ memcpy(table,lpVtbl.unpack('L').first,132)
586
+ table = table.unpack('L*')
587
+ setApplicationName = Win32::API::Function.new(table[32],'PP','L')
588
+
589
+ hr = setApplicationName.call(@pITask,app_w)
590
+
591
+ if hr != S_OK
592
+ raise Error,get_last_error(hr)
511
593
  end
512
594
 
513
- # Returns the user associated with the task or nil if no user has yet
514
- # been associated with the task.
515
- #
516
- def account_information
517
- raise Error, 'null pointer' if @pITS.nil?
518
- raise Error, 'No currently active task' if @pITask.nil?
519
-
520
- lpVtbl = 0.chr * 4
521
- table = 0.chr * 128
522
-
523
- memcpy(lpVtbl, @pITask, 4)
524
- memcpy(table,lpVtbl.unpack('L').first, 128)
525
- table = table.unpack('L*')
526
-
527
- getAccountInformation = Win32::API::Function.new(table[31], 'PP', 'L')
528
-
529
- ptr = 0.chr * 4
530
- hr = getAccountInformation.call(@pITask, ptr)
531
-
532
- if hr == 0x8004130F # SCHED_E_ACCOUNT_INFORMATION_NOT_SET
533
- user = nil
534
- elsif hr >= 0 && hr != 0x80041312 # SCHED_E_NO_SECURITY_SERVICES
535
- str = 0.chr * 256
536
- wcscpy(str, ptr.unpack('L').first)
537
- CoTaskMemFree(ptr.unpack('L').first)
538
- user = wide_to_multi(str)
539
- else
540
- CoTaskMemFree(p.unpack('L').first)
541
- raise Error,get_last_error(hr)
542
- end
543
-
544
- user
595
+ app
596
+ end
597
+
598
+ # Returns the command line parameters for the task.
599
+ #
600
+ def parameters
601
+ raise Error, 'null pointer' if @pITS.nil?
602
+ raise Error, 'No currently active task' if @pITask.nil?
603
+
604
+ lpVtbl = 0.chr * 4
605
+ table = 0.chr * 144
606
+
607
+ memcpy(lpVtbl, @pITask, 4)
608
+ memcpy(table, lpVtbl.unpack('L').first, 144)
609
+ table = table.unpack('L*')
610
+
611
+ getParameters = Win32::API::Function.new(table[35], 'PP', 'L')
612
+ ptr = 0.chr * 4
613
+ hr = getParameters.call(@pITask, ptr)
614
+
615
+ if hr >= S_OK
616
+ str = 0.chr * 256
617
+ wcscpy(str, ptr.unpack('L').first)
618
+ param = wide_to_multi(str)
619
+ CoTaskMemFree(ptr.unpack('L').first)
620
+ else
621
+ raise Error, get_last_error
545
622
  end
546
623
 
547
- # Returns the name of the application associated with the task.
548
- #
549
- def application_name
550
- raise Error, 'null pointer' if @pITS.nil?
551
- raise Error, 'No currently active task' if @pITask.nil?
624
+ param
625
+ end
552
626
 
553
- lpVtbl = 0.chr * 4
554
- table = 0.chr * 136
627
+ # Sets the parameters for the task. These parameters are passed as command
628
+ # line arguments to the application the task will run. To clear the command
629
+ # line parameters set it to an empty string.
630
+ #
631
+ def parameters=(param)
632
+ raise Error, 'null pointer(ts_set_parameters)' if @pITS.nil?
633
+ raise Error, 'No currently active task' if @pITask.nil?
634
+ raise TypeError unless param.is_a?(String)
555
635
 
556
- memcpy(lpVtbl, @pITask,4)
557
- memcpy(table, lpVtbl.unpack('L').first, 136)
558
- table = table.unpack('L*')
636
+ param_w = multi_to_wide(param)
559
637
 
560
- getApplicationName = Win32::API::Function.new(table[33],'PP','L')
638
+ lpVtbl = 0.chr * 4
639
+ table = 0.chr * 140
561
640
 
562
- ptr = 0.chr * 4
563
- hr = getApplicationName.call(@pITask, ptr)
641
+ memcpy(lpVtbl,@pITask,4)
642
+ memcpy(table,lpVtbl.unpack('L').first,140)
643
+ table = table.unpack('L*')
564
644
 
565
- if hr >= S_OK
566
- str = 0.chr * 256
567
- wcscpy(str, ptr.unpack('L').first)
568
- app = wide_to_multi(str)
569
- CoTaskMemFree(ptr.unpack('L').first)
570
- else
571
- raise Error, get_last_error
572
- end
645
+ setParameters = Win32::API::Function.new(table[34],'PP','L')
646
+ hr = setParameters.call(@pITask,param_w)
573
647
 
574
- app
648
+ if hr != S_OK
649
+ raise Error, get_last_error(hr)
575
650
  end
576
651
 
577
- # Sets the application name associated with the task.
578
- #
579
- def application_name=(app)
580
- raise Error, 'null pointer' if @pITS.nil?
581
- raise Error, 'No currently active task' if @pITask.nil?
582
- raise TypeError unless app.is_a?(String)
652
+ param
653
+ end
583
654
 
584
- app_w = multi_to_wide(app)
655
+ # Returns the working directory for the task.
656
+ #
657
+ def working_directory
658
+ raise Error,"fatal error: null pointer(ts_get_parameters)" if @pITS.nil?
659
+ raise Error,"No currently active task" if @pITask.nil?
585
660
 
586
- lpVtbl = 0.chr * 4
587
- table = 0.chr * 132
588
- memcpy(lpVtbl,@pITask,4)
589
- memcpy(table,lpVtbl.unpack('L').first,132)
590
- table = table.unpack('L*')
591
- setApplicationName = Win32::API::Function.new(table[32],'PP','L')
661
+ lpVtbl = 0.chr * 4
662
+ table = 0.chr * 152
592
663
 
593
- hr = setApplicationName.call(@pITask,app_w)
664
+ memcpy(lpVtbl, @pITask,4)
665
+ memcpy(table, lpVtbl.unpack('L').first,152)
666
+ table = table.unpack('L*')
594
667
 
595
- if hr != S_OK
596
- raise Error,get_last_error(hr)
597
- end
598
- app
599
- end
668
+ getWorkingDirectory = Win32::API::Function.new(table[37],'PP','L')
600
669
 
601
- # Returns the command line parameters for the task.
602
- #
603
- def parameters
604
- raise Error, 'null pointer' if @pITS.nil?
605
- raise Error, 'No currently active task' if @pITask.nil?
606
-
607
- lpVtbl = 0.chr * 4
608
- table = 0.chr * 144
609
-
610
- memcpy(lpVtbl, @pITask, 4)
611
- memcpy(table, lpVtbl.unpack('L').first, 144)
612
- table = table.unpack('L*')
613
-
614
- getParameters = Win32::API::Function.new(table[35], 'PP', 'L')
615
- ptr = 0.chr * 4
616
- hr = getParameters.call(@pITask, ptr)
617
-
618
- if hr >= S_OK
619
- str = 0.chr * 256
620
- wcscpy(str, ptr.unpack('L').first)
621
- param = wide_to_multi(str)
622
- CoTaskMemFree(ptr.unpack('L').first)
623
- else
624
- raise Error, get_last_error
625
- end
626
-
627
- param
670
+ ptr = 0.chr * 4
671
+ hr = getWorkingDirectory.call(@pITask, ptr)
672
+
673
+ if hr >= S_OK
674
+ str = 0.chr * 256
675
+ wcscpy(str, ptr.unpack('L').first)
676
+ dir = wide_to_multi(str)
677
+ CoTaskMemFree(ptr.unpack('L').first)
678
+ else
679
+ raise Error, get_last_error
628
680
  end
629
681
 
630
- # Sets the parameters for the task. These parameters are passed as command
631
- # line arguments to the application the task will run. To clear the command
632
- # line parameters set it to an empty string.
633
- #
634
- def parameters=(param)
635
- raise Error, 'null pointer(ts_set_parameters)' if @pITS.nil?
636
- raise Error, 'No currently active task' if @pITask.nil?
637
- raise TypeError unless param.is_a?(String)
682
+ dir
683
+ end
684
+
685
+ # Sets the working directory for the task.
686
+ #
687
+ def working_directory=(dir)
688
+ raise Error, 'null pointer' if @pITS.nil?
689
+ raise Error, 'No currently active task' if @pITask.nil?
690
+ raise TypeError unless dir.is_a?(String)
638
691
 
639
- param_w = multi_to_wide(param)
692
+ dir_w = multi_to_wide(dir)
640
693
 
641
- lpVtbl = 0.chr * 4
642
- table = 0.chr * 140
694
+ lpVtbl = 0.chr * 4
695
+ table = 0.chr * 148
643
696
 
644
- memcpy(lpVtbl,@pITask,4)
645
- memcpy(table,lpVtbl.unpack('L').first,140)
646
- table = table.unpack('L*')
697
+ memcpy(lpVtbl, @pITask,4)
698
+ memcpy(table, lpVtbl.unpack('L').first, 148)
699
+ table = table.unpack('L*')
647
700
 
648
- setParameters = Win32::API::Function.new(table[34],'PP','L')
649
- hr = setParameters.call(@pITask,param_w)
701
+ setWorkingDirectory = Win32::API::Function.new(table[36], 'PP', 'L')
702
+ hr = setWorkingDirectory.call(@pITask, dir_w)
650
703
 
651
- if hr != S_OK
652
- raise Error, get_last_error(hr)
653
- end
654
- param
704
+ if hr != S_OK
705
+ raise Error, get_last_error(hr)
655
706
  end
656
707
 
657
- # Returns the working directory for the task.
658
- #
659
- def working_directory
660
- raise Error,"fatal error: null pointer(ts_get_parameters)" if @pITS.nil?
661
- raise Error,"No currently active task" if @pITask.nil?
708
+ dir
709
+ end
710
+
711
+ # Returns the task's priority level. Possible values are 'idle',
712
+ # 'normal', 'high', 'realtime', 'below_normal', 'above_normal',
713
+ # and 'unknown'.
714
+ #
715
+ def priority
716
+ raise Error, 'null pointer(ts_get_priority)' if @pITS.nil?
717
+ raise Error, 'No currently active task' if @pITask.nil?
718
+
719
+ lpVtbl = 0.chr * 4
720
+ table = 0.chr * 160
721
+
722
+ memcpy(lpVtbl, @pITask, 4)
723
+ memcpy(table, lpVtbl.unpack('L').first, 160)
724
+ table = table.unpack('L*')
725
+
726
+ getPriority = Win32::API::Function.new(table[39], 'PP', 'L')
727
+
728
+ ptr = 0.chr * 4
729
+ hr = getPriority.call(@pITask, ptr)
730
+
731
+ if hr >= S_OK
732
+ pri = ptr.unpack('L').first
733
+ if (pri & IDLE_PRIORITY_CLASS) != 0
734
+ priority = 'idle'
735
+ elsif (pri & NORMAL_PRIORITY_CLASS) != 0
736
+ priority = 'normal'
737
+ elsif (pri & HIGH_PRIORITY_CLASS) != 0
738
+ priority = 'high'
739
+ elsif (pri & REALTIME_PRIORITY_CLASS) != 0
740
+ priority = 'realtime'
741
+ elsif (pri & BELOW_NORMAL_PRIORITY_CLASS) != 0
742
+ priority = 'below_normal'
743
+ elsif (pri & ABOVE_NORMAL_PRIORITY_CLASS) != 0
744
+ priority = 'above_normal'
745
+ else
746
+ priority = 'unknown'
747
+ end
748
+ else
749
+ raise Error, get_last_error
750
+ end
662
751
 
663
- lpVtbl = 0.chr * 4
664
- table = 0.chr * 152
752
+ priority
753
+ end
665
754
 
666
- memcpy(lpVtbl, @pITask,4)
667
- memcpy(table, lpVtbl.unpack('L').first,152)
668
- table = table.unpack('L*')
755
+ # Sets the priority of the task. The +priority+ should be a numeric
756
+ # priority constant value.
757
+ #
758
+ def priority=(priority)
759
+ raise Error, 'null pointer' if @pITS.nil?
760
+ raise Error, 'No currently active task' if @pITask.nil?
761
+ raise TypeError unless priority.is_a?(Numeric)
669
762
 
670
- getWorkingDirectory = Win32::API::Function.new(table[37],'PP','L')
763
+ lpVtbl = 0.chr * 4
764
+ table = 0.chr * 156
671
765
 
672
- ptr = 0.chr * 4
673
- hr = getWorkingDirectory.call(@pITask, ptr)
766
+ memcpy(lpVtbl, @pITask, 4)
767
+ memcpy(table, lpVtbl.unpack('L').first, 156)
768
+ table = table.unpack('L*')
674
769
 
675
- if hr >= S_OK
676
- str = 0.chr * 256
677
- wcscpy(str, ptr.unpack('L').first)
678
- dir = wide_to_multi(str)
679
- CoTaskMemFree(ptr.unpack('L').first)
680
- else
681
- raise Error, get_last_error
682
- end
770
+ setPriority = Win32::API::Function.new(table[38], 'PL', 'L')
771
+ hr = setPriority.call(@pITask, priority)
683
772
 
684
- dir
773
+ if hr != S_OK
774
+ raise Error, get_last_error(hr)
685
775
  end
686
776
 
687
- # Sets the working directory for the task.
688
- #
689
- def working_directory=(dir)
690
- raise Error, 'null pointer' if @pITS.nil?
691
- raise Error, 'No currently active task' if @pITask.nil?
692
- raise TypeError unless dir.is_a?(String)
777
+ priority
778
+ end
693
779
 
694
- dir_w = multi_to_wide(dir)
780
+ # Creates a new work item (scheduled job) with the given +trigger+. The
781
+ # trigger variable is a hash of options that define when the scheduled
782
+ # job should run.
783
+ #
784
+ def new_work_item(task, trigger)
785
+ raise TypeError unless trigger.is_a?(Hash)
786
+ raise Error, 'null pointer' if @pITS.nil?
695
787
 
696
- lpVtbl = 0.chr * 4
697
- table = 0.chr * 148
788
+ # I'm working around github issue #1 here.
789
+ enum.each{ |name|
790
+ if name.downcase == task.downcase + '.job'
791
+ raise Error, "task '#{task}' already exists"
792
+ end
793
+ }
698
794
 
699
- memcpy(lpVtbl, @pITask,4)
700
- memcpy(table, lpVtbl.unpack('L').first, 148)
701
- table = table.unpack('L*')
795
+ trigger = transform_and_validate(trigger)
702
796
 
703
- setWorkingDirectory = Win32::API::Function.new(table[36], 'PP', 'L')
704
- hr = setWorkingDirectory.call(@pITask, dir_w)
797
+ if @pITask
798
+ lpVtbl = 0.chr * 4
799
+ table = 0.chr * 12
705
800
 
706
- if hr != S_OK
707
- raise Error, get_last_error(hr)
708
- end
801
+ memcpy(lpVtbl, @pITask, 4)
802
+ memcpy(table, lpVtbl.unpack('L').first, 12)
803
+ table = table.unpack('L*')
709
804
 
710
- dir
805
+ release = Win32::API::Function.new(table[2], 'P', 'L')
806
+ release.call(@pITask)
807
+
808
+ @pITask = nil
711
809
  end
712
810
 
713
- # Returns the task's priority level. Possible values are 'idle',
714
- # 'normal', 'high', 'realtime', 'below_normal', 'above_normal',
715
- # and 'unknown'.
716
- #
717
- def priority
718
- raise Error, 'null pointer(ts_get_priority)' if @pITS.nil?
719
- raise Error, 'No currently active task' if @pITask.nil?
720
-
721
- lpVtbl = 0.chr * 4
722
- table = 0.chr * 160
723
-
724
- memcpy(lpVtbl, @pITask, 4)
725
- memcpy(table, lpVtbl.unpack('L').first, 160)
726
- table = table.unpack('L*')
727
-
728
- getPriority = Win32::API::Function.new(table[39], 'PP', 'L')
729
-
730
- ptr = 0.chr * 4
731
- hr = getPriority.call(@pITask, ptr)
732
-
733
- if hr >= S_OK
734
- pri = ptr.unpack('L').first
735
- if (pri & IDLE_PRIORITY_CLASS) != 0
736
- priority = 'idle'
737
- elsif (pri & NORMAL_PRIORITY_CLASS) != 0
738
- priority = 'normal'
739
- elsif (pri & HIGH_PRIORITY_CLASS) != 0
740
- priority = 'high'
741
- elsif (pri & REALTIME_PRIORITY_CLASS) != 0
742
- priority = 'realtime'
743
- elsif (pri & BELOW_NORMAL_PRIORITY_CLASS) != 0
744
- priority = 'below_normal'
745
- elsif (pri & ABOVE_NORMAL_PRIORITY_CLASS) != 0
746
- priority = 'above_normal'
747
- else
748
- priority = 'unknown'
749
- end
750
- else
751
- raise Error, get_last_error
752
- end
811
+ task = multi_to_wide(task)
812
+ lpVtbl = 0.chr * 4
813
+ table = 0.chr * 36
753
814
 
754
- priority
815
+ memcpy(lpVtbl, @pITS, 4)
816
+ memcpy(table, lpVtbl.unpack('L').first, 36)
817
+ table = table.unpack('L*')
818
+
819
+ newWorkItem = Win32::API::Function.new(table[8], 'PPPPP', 'L')
820
+
821
+ ptr = 0.chr * 4
822
+
823
+ hr = newWorkItem.call(@pITS, task, CLSID_CTask, IID_ITask, ptr)
824
+
825
+ if FAILED(hr)
826
+ raise Error, get_last_error
755
827
  end
756
828
 
757
- # Sets the priority of the task. The +priority+ should be a numeric
758
- # priority constant value.
759
- #
760
- def priority=(priority)
761
- raise Error, 'null pointer' if @pITS.nil?
762
- raise Error, 'No currently active task' if @pITask.nil?
763
- raise TypeError unless priority.is_a?(Numeric)
829
+ @pITask = ptr.unpack('L').first
830
+ lpVtbl = 0.chr * 4
831
+ table = 0.chr * 16
764
832
 
765
- lpVtbl = 0.chr * 4
766
- table = 0.chr * 156
833
+ # Without the 'enum.include?' check above the code segfaults here if the
834
+ # task already exists. This should probably be handled properly instead
835
+ # of simply avoiding the issue.
767
836
 
768
- memcpy(lpVtbl, @pITask, 4)
769
- memcpy(table, lpVtbl.unpack('L').first, 156)
770
- table = table.unpack('L*')
837
+ memcpy(lpVtbl, @pITask, 4)
838
+ memcpy(table, lpVtbl.unpack('L').first, 16)
839
+ table = table.unpack('L*')
771
840
 
772
- setPriority = Win32::API::Function.new(table[38], 'PL', 'L')
773
- hr = setPriority.call(@pITask, priority)
841
+ createTrigger = Win32::API::Function.new(table[3], 'PPP', 'L')
842
+ p1 = 0.chr * 4
843
+ p2 = 0.chr * 4
774
844
 
775
- if hr != S_OK
776
- raise Error, get_last_error(hr)
777
- end
845
+ hr = createTrigger.call(@pITask, p1, p2)
778
846
 
779
- priority
847
+ if hr != S_OK
848
+ raise Error, get_last_error
780
849
  end
781
850
 
782
- # Creates a new work item (scheduled job) with the given +trigger+. The
783
- # trigger variable is a hash of options that define when the scheduled
784
- # job should run.
785
- #
786
- def new_work_item(task, trigger)
787
- raise TypeError unless trigger.is_a?(Hash)
788
- raise Error, 'null pointer' if @pITS.nil?
789
-
790
- trigger = transform_and_validate(trigger)
791
-
792
- if @pITask
793
- lpVtbl = 0.chr * 4
794
- table = 0.chr * 12
795
-
796
- memcpy(lpVtbl, @pITask, 4)
797
- memcpy(table, lpVtbl.unpack('L').first, 12)
798
- table = table.unpack('L*')
799
-
800
- release = Win32::API::Function.new(table[2], 'P', 'L')
801
- release.call(@pITask)
802
-
803
- @pITask = nil
804
- end
805
-
806
- task = multi_to_wide(task)
807
- lpVtbl = 0.chr * 4
808
- table = 0.chr * 36
809
-
810
- memcpy(lpVtbl, @pITS, 4)
811
- memcpy(table, lpVtbl.unpack('L').first, 36)
812
- table = table.unpack('L*')
813
-
814
- newWorkItem = Win32::API::Function.new(table[8], 'PPPPP', 'L')
815
-
816
- ptr = 0.chr * 4
817
-
818
- hr = newWorkItem.call(@pITS, task, CLSID_CTask, IID_ITask, ptr)
819
-
820
- if FAILED(hr)
821
- raise Error, get_last_error
822
- end
823
-
824
- @pITask = ptr.unpack('L').first
825
- lpVtbl = 0.chr * 4
826
- table = 0.chr * 16
827
-
828
- memcpy(lpVtbl, @pITask, 4)
829
- memcpy(table, lpVtbl.unpack('L').first, 16)
830
- table = table.unpack('L*')
831
-
832
- createTrigger = Win32::API::Function.new(table[3], 'PPP', 'L')
833
- p1 = 0.chr * 4
834
- p2 = 0.chr * 4
835
-
836
- hr = createTrigger.call(@pITask, p1, p2)
837
-
838
- if hr != S_OK
839
- raise Error, get_last_error
840
- end
841
-
842
- pITaskTrigger = p2.unpack('L').first
843
- lpVtbl = 0.chr * 4
844
- table = 0.chr * 16
845
-
846
- memcpy(lpVtbl, pITaskTrigger, 4)
847
- memcpy(table, lpVtbl.unpack('L').first, 16)
848
- table = table.unpack('L*')
849
-
850
- release = Win32::API::Function.new(table[2], 'P', 'L')
851
- setTrigger = Win32::API::Function.new(table[3], 'PP', 'L')
852
-
853
- type1 = 0
854
- type2 = 0
855
- tmp = trigger['type']
856
- tmp = nil unless tmp.is_a?(Hash)
857
-
858
- case trigger['trigger_type']
859
- when TASK_TIME_TRIGGER_DAILY
860
- if tmp && tmp['days_interval']
861
- type1 = [tmp['days_interval'],0].pack('SS').unpack('L').first
862
- end
863
- when TASK_TIME_TRIGGER_WEEKLY
864
- if tmp && tmp['weeks_interval'] && tmp['days_of_week']
865
- type1 = [tmp['weeks_interval'],tmp['days_of_week']].pack('SS').unpack('L').first
866
- end
867
- when TASK_TIME_TRIGGER_MONTHLYDATE
868
- if tmp && tmp['months'] && tmp['days']
869
- type2 = [tmp['months'],0].pack('SS').unpack('L').first
870
- type1 = tmp['days']
871
- end
872
- when TASK_TIME_TRIGGER_MONTHLYDOW
873
- if tmp && tmp['weeks'] && tmp['days_of_week'] && tmp['months']
874
- type1 = [tmp['weeks'],tmp['days_of_week']].pack('SS').unpack('L').first
875
- type2 = [tmp['months'],0].pack('SS').unpack('L').first
876
- end
877
- when TASK_TIME_TRIGGER_ONCE
878
- # Do nothing. The Type member of the TASK_TRIGGER struct is ignored.
879
- else
880
- raise Error, 'Unknown trigger type'
881
- end
882
-
883
- pTrigger = [
884
- 48,
885
- 0,
886
- trigger['start_year'] || 0,
887
- trigger['start_month'] || 0,
888
- trigger['start_day'] || 0,
889
- trigger['end_year'] || 0,
890
- trigger['end_month'] || 0,
891
- trigger['end_day'] || 0,
892
- trigger['start_hour'] || 0,
893
- trigger['start_minute'] || 0,
894
- trigger['minutes_duration'] || 0,
895
- trigger['minutes_interval'] || 0,
896
- trigger['flags'] || 0,
897
- trigger['trigger_type'] || 0,
898
- type1,
899
- type2,
900
- 0,
901
- trigger['random_minutes_interval'] || 0
902
- ].pack('S10L4LLSS')
903
-
904
- hr = setTrigger.call(pITaskTrigger, pTrigger)
905
-
906
- if hr != S_OK
907
- raise Error, get_last_error
908
- end
909
-
910
- release.call(pITaskTrigger)
911
-
912
- self
851
+ pITaskTrigger = p2.unpack('L').first
852
+ lpVtbl = 0.chr * 4
853
+ table = 0.chr * 16
854
+
855
+ memcpy(lpVtbl, pITaskTrigger, 4)
856
+ memcpy(table, lpVtbl.unpack('L').first, 16)
857
+ table = table.unpack('L*')
858
+
859
+ release = Win32::API::Function.new(table[2], 'P', 'L')
860
+ setTrigger = Win32::API::Function.new(table[3], 'PP', 'L')
861
+
862
+ type1 = 0
863
+ type2 = 0
864
+ tmp = trigger['type']
865
+ tmp = nil unless tmp.is_a?(Hash)
866
+
867
+ case trigger['trigger_type']
868
+ when TASK_TIME_TRIGGER_DAILY
869
+ if tmp && tmp['days_interval']
870
+ type1 = [tmp['days_interval'],0].pack('SS').unpack('L').first
871
+ end
872
+ when TASK_TIME_TRIGGER_WEEKLY
873
+ if tmp && tmp['weeks_interval'] && tmp['days_of_week']
874
+ type1 = [tmp['weeks_interval'],tmp['days_of_week']].pack('SS').unpack('L').first
875
+ end
876
+ when TASK_TIME_TRIGGER_MONTHLYDATE
877
+ if tmp && tmp['months'] && tmp['days']
878
+ type2 = [tmp['months'],0].pack('SS').unpack('L').first
879
+ type1 = tmp['days']
880
+ end
881
+ when TASK_TIME_TRIGGER_MONTHLYDOW
882
+ if tmp && tmp['weeks'] && tmp['days_of_week'] && tmp['months']
883
+ type1 = [tmp['weeks'],tmp['days_of_week']].pack('SS').unpack('L').first
884
+ type2 = [tmp['months'],0].pack('SS').unpack('L').first
885
+ end
886
+ when TASK_TIME_TRIGGER_ONCE
887
+ # Do nothing. The Type member of the TASK_TRIGGER struct is ignored.
888
+ else
889
+ raise Error, 'Unknown trigger type'
890
+ end
891
+
892
+ pTrigger = [
893
+ 48,
894
+ 0,
895
+ trigger['start_year'] || 0,
896
+ trigger['start_month'] || 0,
897
+ trigger['start_day'] || 0,
898
+ trigger['end_year'] || 0,
899
+ trigger['end_month'] || 0,
900
+ trigger['end_day'] || 0,
901
+ trigger['start_hour'] || 0,
902
+ trigger['start_minute'] || 0,
903
+ trigger['minutes_duration'] || 0,
904
+ trigger['minutes_interval'] || 0,
905
+ trigger['flags'] || 0,
906
+ trigger['trigger_type'] || 0,
907
+ type1,
908
+ type2,
909
+ 0,
910
+ trigger['random_minutes_interval'] || 0
911
+ ].pack('S10L4LLSS')
912
+
913
+ hr = setTrigger.call(pITaskTrigger, pTrigger)
914
+
915
+ if hr != S_OK
916
+ raise Error, get_last_error
913
917
  end
914
918
 
915
- alias :new_task :new_work_item
919
+ release.call(pITaskTrigger)
920
+ end
916
921
 
917
- # Returns the number of triggers associated with the active task.
918
- #
919
- def trigger_count
920
- raise Error, "null pointer" if @pITS.nil?
921
- raise Error, "No currently active task" if @pITask.nil?
922
+ alias :new_task :new_work_item
922
923
 
923
- lpVtbl = 0.chr * 4
924
- table = 0.chr * 24
924
+ # Returns the number of triggers associated with the active task.
925
+ #
926
+ def trigger_count
927
+ raise Error, "null pointer" if @pITS.nil?
928
+ raise Error, "No currently active task" if @pITask.nil?
925
929
 
926
- memcpy(lpVtbl, @pITask,4)
927
- memcpy(table, lpVtbl.unpack('L').first, 24)
928
- table = table.unpack('L*')
930
+ lpVtbl = 0.chr * 4
931
+ table = 0.chr * 24
929
932
 
930
- getTriggerCount = Win32::API::Function.new(table[5], 'PP', 'L')
931
- ptr = 0.chr * 4
932
- hr = getTriggerCount.call(@pITask, ptr)
933
+ memcpy(lpVtbl, @pITask,4)
934
+ memcpy(table, lpVtbl.unpack('L').first, 24)
935
+ table = table.unpack('L*')
933
936
 
934
- if hr >= S_OK
935
- count = ptr.unpack('L').first
936
- else
937
- raise Error, get_last_error
938
- end
937
+ getTriggerCount = Win32::API::Function.new(table[5], 'PP', 'L')
938
+ ptr = 0.chr * 4
939
+ hr = getTriggerCount.call(@pITask, ptr)
939
940
 
940
- count
941
+ if hr >= S_OK
942
+ count = ptr.unpack('L').first
943
+ else
944
+ raise Error, get_last_error
941
945
  end
942
946
 
943
- # Returns a string that describes the current trigger at the specified
944
- # index for the active task.
945
- #
946
- # Example: "At 7:14 AM every day, starting 4/11/2009"
947
- #
948
- def trigger_string(index)
949
- raise Error, 'null pointer' if @pITS.nil?
950
- raise Error, 'No currently active task' if @pITask.nil?
951
- raise TypeError unless index.is_a?(Numeric)
952
-
953
- lpVtbl = 0.chr * 4
954
- table = 0.chr * 32
955
-
956
- memcpy(lpVtbl, @pITask, 4)
957
- memcpy(table, lpVtbl.unpack('L').first, 32)
958
- table = table.unpack('L*')
959
-
960
- getTriggerString = Win32::API::Function.new(table[7], 'PLP', 'L')
961
- ptr = 0.chr * 4
962
- hr = getTriggerString.call(@pITask, index, ptr)
963
-
964
- if hr == S_OK
965
- str = 0.chr * 256
966
- wcscpy(str, ptr.unpack('L').first)
967
- trigger = wide_to_multi(str)
968
- CoTaskMemFree(ptr.unpack('L').first)
969
- else
970
- raise Error, get_last_error
971
- end
972
-
973
- trigger
947
+ count
948
+ end
949
+
950
+ # Returns a string that describes the current trigger at the specified
951
+ # index for the active task.
952
+ #
953
+ # Example: "At 7:14 AM every day, starting 4/11/2009"
954
+ #
955
+ def trigger_string(index)
956
+ raise Error, 'null pointer' if @pITS.nil?
957
+ raise Error, 'No currently active task' if @pITask.nil?
958
+ raise TypeError unless index.is_a?(Numeric)
959
+
960
+ lpVtbl = 0.chr * 4
961
+ table = 0.chr * 32
962
+
963
+ memcpy(lpVtbl, @pITask, 4)
964
+ memcpy(table, lpVtbl.unpack('L').first, 32)
965
+ table = table.unpack('L*')
966
+
967
+ getTriggerString = Win32::API::Function.new(table[7], 'PLP', 'L')
968
+ ptr = 0.chr * 4
969
+ hr = getTriggerString.call(@pITask, index, ptr)
970
+
971
+ if hr == S_OK
972
+ str = 0.chr * 256
973
+ wcscpy(str, ptr.unpack('L').first)
974
+ trigger = wide_to_multi(str)
975
+ CoTaskMemFree(ptr.unpack('L').first)
976
+ else
977
+ raise Error, get_last_error
974
978
  end
975
979
 
976
- # Deletes the trigger at the specified index.
977
- #
978
- def delete_trigger(index)
979
- raise Error, 'null pointer' if @pITS.nil?
980
- raise Error, 'No currently active task' if @pITask.nil?
980
+ trigger
981
+ end
981
982
 
982
- lpVtbl = 0.chr * 4
983
- table = 0.chr * 20
983
+ # Deletes the trigger at the specified index.
984
+ #
985
+ def delete_trigger(index)
986
+ raise Error, 'null pointer' if @pITS.nil?
987
+ raise Error, 'No currently active task' if @pITask.nil?
984
988
 
985
- memcpy(lpVtbl, @pITask, 4)
986
- memcpy(table, lpVtbl.unpack('L').first, 20)
987
- table = table.unpack('L*')
989
+ lpVtbl = 0.chr * 4
990
+ table = 0.chr * 20
988
991
 
989
- deleteTrigger = Win32::API::Function.new(table[4], 'PL', 'L')
990
- hr = deleteTrigger.call(@pITask,index)
992
+ memcpy(lpVtbl, @pITask, 4)
993
+ memcpy(table, lpVtbl.unpack('L').first, 20)
994
+ table = table.unpack('L*')
991
995
 
992
- if hr != S_OK
993
- raise Error, get_last_error
994
- end
996
+ deleteTrigger = Win32::API::Function.new(table[4], 'PL', 'L')
997
+ hr = deleteTrigger.call(@pITask,index)
995
998
 
996
- index
999
+ if hr != S_OK
1000
+ raise Error, get_last_error
997
1001
  end
998
1002
 
999
- # Returns a hash that describes the trigger at the given index for the
1000
- # current task.
1001
- #
1002
- def trigger(index)
1003
- raise Error, 'null pointer' if @pITS.nil?
1004
- raise Error, 'No currently active task' if @pITask.nil?
1005
-
1006
- lpVtbl = 0.chr * 4
1007
- table = 0.chr * 28
1008
-
1009
- memcpy(lpVtbl, @pITask, 4)
1010
- memcpy(table, lpVtbl.unpack('L').first, 28)
1011
- table = table.unpack('L*')
1012
-
1013
- getTrigger = Win32::API::Function.new(table[6], 'PLP', 'L')
1014
- ptr = 0.chr * 4
1015
- hr = getTrigger.call(@pITask, index, ptr)
1016
-
1017
- if hr != S_OK
1018
- raise Error, get_last_error
1019
- end
1020
-
1021
- pITaskTrigger = ptr.unpack('L').first
1022
- lpVtbl = 0.chr * 4
1023
- table = 0.chr * 20
1024
-
1025
- memcpy(lpVtbl, pITaskTrigger, 4)
1026
- memcpy(table, lpVtbl.unpack('L').first, 20)
1027
- table = table.unpack('L*')
1028
-
1029
- release = Win32::API::Function.new(table[2], 'P', 'L')
1030
- getTrigger = Win32::API::Function.new(table[4], 'PP', 'L')
1031
-
1032
- pTrigger = [48].pack('S') + 0.chr * 46
1033
- hr = getTrigger.call(pITaskTrigger, pTrigger)
1034
-
1035
- if hr != S_OK
1036
- error = get_last_error
1037
- release.call(pITaskTrigger)
1038
- raise Error, error
1039
- end
1040
-
1041
- tr = pTrigger.unpack('S10L4LLSS')
1042
-
1043
- trigger = {}
1044
- trigger['start_year'] = tr[2]
1045
- trigger['start_month'] = tr[3]
1046
- trigger['start_day'] = tr[4]
1047
- trigger['end_year'] = tr[5]
1048
- trigger['end_month'] = tr[6]
1049
- trigger['end_day'] = tr[7]
1050
- trigger['start_hour'] = tr[8]
1051
- trigger['start_minute'] = tr[9]
1052
- trigger['minutes_duration'] = tr[10]
1053
- trigger['minutes_interval'] = tr[11]
1054
- trigger['flags'] = tr[12]
1055
- trigger['trigger_type'] = tr[13]
1056
- trigger['random_minutes_interval'] = tr[17]
1057
-
1058
- case tr[13]
1059
- when TASK_TIME_TRIGGER_DAILY
1060
- tmp = {}
1061
- tmp['days_interval'] = [tr[14]].pack('L').unpack('SS').first
1062
- trigger['type'] = tmp
1063
- when TASK_TIME_TRIGGER_WEEKLY
1064
- tmp = {}
1065
- tmp['weeks_interval'],tmp['days_of_week'] = [tr[14]].pack('L').unpack('SS')
1066
- trigger['type'] = tmp
1067
- when TASK_TIME_TRIGGER_MONTHLYDATE
1068
- tmp = {}
1069
- tmp['days'] = tr[14]
1070
- tmp['months'] = [tr[15]].pack('L').unpack('SS').first
1071
- trigger['type'] = tmp
1072
- when TASK_TIME_TRIGGER_MONTHLYDOW
1073
- tmp = {}
1074
- tmp['weeks'],tmp['days_of_week'] = [tr[14]].pack('L').unpack('SS')
1075
- tmp['months'] = [tr[15]].pack('L').unpack('SS').first
1076
- trigger['type'] = tmp
1077
- when TASK_TIME_TRIGGER_ONCE
1078
- tmp = {}
1079
- tmp['once'] = nil
1080
- trigger['type'] = tmp
1081
- else
1082
- raise Error, 'Unknown trigger type'
1083
- end
1084
-
1085
- release.call(pITaskTrigger)
1086
-
1087
- trigger
1003
+ index
1004
+ end
1005
+
1006
+ # Returns a hash that describes the trigger at the given index for the
1007
+ # current task.
1008
+ #
1009
+ def trigger(index)
1010
+ raise Error, 'null pointer' if @pITS.nil?
1011
+ raise Error, 'No currently active task' if @pITask.nil?
1012
+
1013
+ lpVtbl = 0.chr * 4
1014
+ table = 0.chr * 28
1015
+
1016
+ memcpy(lpVtbl, @pITask, 4)
1017
+ memcpy(table, lpVtbl.unpack('L').first, 28)
1018
+ table = table.unpack('L*')
1019
+
1020
+ getTrigger = Win32::API::Function.new(table[6], 'PLP', 'L')
1021
+ ptr = 0.chr * 4
1022
+ hr = getTrigger.call(@pITask, index, ptr)
1023
+
1024
+ if hr != S_OK
1025
+ raise Error, get_last_error
1088
1026
  end
1089
1027
 
1090
- # Sets the trigger for the currently active task.
1091
- #
1092
- def trigger=(trigger)
1093
- raise Error, 'null pointer' if @pITS.nil?
1094
- raise Error, 'No currently active task' if @pITask.nil?
1095
- raise TypeError unless trigger.is_a?(Hash)
1096
-
1097
- lpVtbl = 0.chr * 4
1098
- table = 0.chr * 16
1099
-
1100
- memcpy(lpVtbl, @pITask, 4)
1101
- memcpy(table, lpVtbl.unpack('L').first, 16)
1102
- table = table.unpack('L*')
1103
-
1104
- createTrigger = Win32::API::Function.new(table[3], 'PPP', 'L')
1105
-
1106
- p1 = 0.chr * 4
1107
- p2 = 0.chr * 4
1108
-
1109
- hr = createTrigger.call(@pITask, p1, p2)
1110
-
1111
- if hr != S_OK
1112
- raise Error, get_last_error
1113
- end
1114
-
1115
- pITaskTrigger = p2.unpack('L').first
1116
- lpVtbl = 0.chr * 4
1117
- table = 0.chr * 16
1118
-
1119
- memcpy(lpVtbl, pITaskTrigger, 4)
1120
- memcpy(table, lpVtbl.unpack('L').first, 16)
1121
- table = table.unpack('L*')
1122
-
1123
- release = Win32::API::Function.new(table[2], 'P', 'L')
1124
- setTrigger = Win32::API::Function.new(table[3], 'PP', 'L')
1125
-
1126
- type1 = 0
1127
- type2 = 0
1128
- tmp = trigger['type']
1129
- tmp = nil unless tmp.is_a?(Hash)
1130
-
1131
- case trigger['trigger_type']
1132
- when TASK_TIME_TRIGGER_DAILY
1133
- if tmp && tmp['days_interval']
1134
- type1 = [tmp['days_interval'],0].pack('SS').unpack('L').first
1135
- end
1136
- when TASK_TIME_TRIGGER_WEEKLY
1137
- if tmp && tmp['weeks_interval'] && tmp['days_of_week']
1138
- type1 = [tmp['weeks_interval'],tmp['days_of_week']].pack('SS').unpack('L').first
1139
- end
1140
- when TASK_TIME_TRIGGER_MONTHLYDATE
1141
- if tmp && tmp['months'] && tmp['days']
1142
- type2 = [tmp['months'],0].pack('SS').unpack('L').first
1143
- type1 = tmp['days']
1144
- end
1145
- when TASK_TIME_TRIGGER_MONTHLYDOW
1146
- if tmp && tmp['weeks'] && tmp['days_of_week'] && tmp['months']
1147
- type1 = [tmp['weeks'],tmp['days_of_week']].pack('SS').unpack('L').first
1148
- type2 = [tmp['months'],0].pack('SS').unpack('L').first
1149
- end
1150
- when TASK_TIME_TRIGGER_ONCE
1151
- # Do nothing. The Type member of the TASK_TRIGGER struct is ignored.
1152
- else
1153
- raise Error, 'Unknown trigger type'
1154
- end
1155
-
1156
- pTrigger = [
1157
- 48,
1158
- 0,
1159
- trigger['start_year'] || 0,
1160
- trigger['start_month'] || 0,
1161
- trigger['start_day'] || 0,
1162
- trigger['end_year'] || 0,
1163
- trigger['end_month'] || 0,
1164
- trigger['end_day'] || 0,
1165
- trigger['start_hour'] || 0,
1166
- trigger['start_minute'] || 0,
1167
- trigger['minutes_duration'] || 0,
1168
- trigger['minutes_interval'] || 0,
1169
- trigger['flags'] || 0,
1170
- trigger['trigger_type'] || 0,
1171
- type1,
1172
- type2,
1173
- 0,
1174
- trigger['random_minutes_interval'] || 0
1175
- ].pack('S10L4LLSS')
1176
-
1177
- hr = setTrigger.call(pITaskTrigger, pTrigger)
1178
-
1179
- if hr != S_OK
1180
- raise Error, get_last_error
1181
- end
1182
-
1183
- release.call(pITaskTrigger)
1184
-
1185
- trigger
1028
+ pITaskTrigger = ptr.unpack('L').first
1029
+ lpVtbl = 0.chr * 4
1030
+ table = 0.chr * 20
1031
+
1032
+ memcpy(lpVtbl, pITaskTrigger, 4)
1033
+ memcpy(table, lpVtbl.unpack('L').first, 20)
1034
+ table = table.unpack('L*')
1035
+
1036
+ release = Win32::API::Function.new(table[2], 'P', 'L')
1037
+ getTrigger = Win32::API::Function.new(table[4], 'PP', 'L')
1038
+
1039
+ pTrigger = [48].pack('S') + 0.chr * 46
1040
+ hr = getTrigger.call(pITaskTrigger, pTrigger)
1041
+
1042
+ if hr != S_OK
1043
+ error = get_last_error
1044
+ release.call(pITaskTrigger)
1045
+ raise Error, error
1186
1046
  end
1187
1047
 
1188
- # Adds a trigger at the specified index.
1189
- #
1190
- def add_trigger(index, trigger)
1191
- raise Error, 'null pointer' if @pITS.nil?
1192
- raise Error, 'No currently active task' if @pITask.nil?
1193
- raise TypeError unless trigger.is_a?(Hash)
1194
-
1195
- lpVtbl = 0.chr * 4
1196
- table = 0.chr * 28
1197
-
1198
- memcpy(lpVtbl, @pITask, 4)
1199
- memcpy(table, lpVtbl.unpack('L').first, 28)
1200
- table = table.unpack('L*')
1201
-
1202
- getTrigger = Win32::API::Function.new(table[6], 'PLP', 'L')
1203
- ptr = 0.chr * 4
1204
- hr = getTrigger.call(@pITask, index, ptr)
1205
-
1206
- if hr != S_OK
1207
- raise Error, get_last_error
1208
- end
1209
-
1210
- pITaskTrigger = ptr.unpack('L').first
1211
- lpVtbl = 0.chr * 4
1212
- table = 0.chr * 16
1213
-
1214
- memcpy(lpVtbl, pITaskTrigger,4)
1215
- memcpy(table, lpVtbl.unpack('L').first,16)
1216
- table = table.unpack('L*')
1217
-
1218
- release = Win32::API::Function.new(table[2], 'P', 'L')
1219
- setTrigger = Win32::API::Function.new(table[3], 'PP', 'L')
1220
-
1221
- type1 = 0
1222
- type2 = 0
1223
- tmp = trigger['type']
1224
- tmp = nil unless tmp.is_a?(Hash)
1225
-
1226
- case trigger['trigger_type']
1227
- when TASK_TIME_TRIGGER_DAILY
1228
- if tmp && tmp['days_interval']
1229
- type1 = [tmp['days_interval'],0].pack('SS').unpack('L').first
1230
- end
1231
- when TASK_TIME_TRIGGER_WEEKLY
1232
- if tmp && tmp['weeks_interval'] && tmp['days_of_week']
1233
- type1 = [tmp['weeks_interval'],tmp['days_of_week']].pack('SS').unpack('L').first
1234
- end
1235
- when TASK_TIME_TRIGGER_MONTHLYDATE
1236
- if tmp && tmp['months'] && tmp['days']
1237
- type2 = [tmp['months'],0].pack('SS').unpack('L').first
1238
- type1 = tmp['days']
1239
- end
1240
- when TASK_TIME_TRIGGER_MONTHLYDOW
1241
- if tmp && tmp['weeks'] && tmp['days_of_week'] && tmp['months']
1242
- type1 = [tmp['weeks'],tmp['days_of_week']].pack('SS').unpack('L').first
1243
- type2 = [tmp['months'],0].pack('SS').unpack('L').first
1244
- end
1245
- when TASK_TIME_TRIGGER_ONCE
1246
- # Do nothing. The Type member of the TASK_TRIGGER struct is ignored.
1247
- else
1248
- raise Error, 'Unknown trigger type'
1249
- end
1250
-
1251
- pTrigger = [
1252
- 48,
1253
- 0,
1254
- trigger['start_year'] || 0,
1255
- trigger['start_month'] || 0,
1256
- trigger['start_day'] || 0,
1257
- trigger['end_year'] || 0,
1258
- trigger['end_month'] || 0,
1259
- trigger['end_day'] || 0,
1260
- trigger['start_hour'] || 0,
1261
- trigger['start_minute'] || 0,
1262
- trigger['minutes_duration'] || 0,
1263
- trigger['minutes_interval'] || 0,
1264
- trigger['flags'] || 0,
1265
- trigger['trigger_type'] || 0,
1266
- type1,
1267
- type2,
1268
- 0,
1269
- trigger['random_minutes_interval'] || 0
1270
- ].pack('S10L4LLSS')
1271
-
1272
- hr = setTrigger.call(pITaskTrigger, pTrigger)
1273
-
1274
- if hr != S_OK
1275
- raise Error, get_last_error
1276
- end
1277
-
1278
- release.call(pITaskTrigger)
1279
- true
1048
+ tr = pTrigger.unpack('S10L4LLSS')
1049
+
1050
+ trigger = {}
1051
+ trigger['start_year'] = tr[2]
1052
+ trigger['start_month'] = tr[3]
1053
+ trigger['start_day'] = tr[4]
1054
+ trigger['end_year'] = tr[5]
1055
+ trigger['end_month'] = tr[6]
1056
+ trigger['end_day'] = tr[7]
1057
+ trigger['start_hour'] = tr[8]
1058
+ trigger['start_minute'] = tr[9]
1059
+ trigger['minutes_duration'] = tr[10]
1060
+ trigger['minutes_interval'] = tr[11]
1061
+ trigger['flags'] = tr[12]
1062
+ trigger['trigger_type'] = tr[13]
1063
+ trigger['random_minutes_interval'] = tr[17]
1064
+
1065
+ case tr[13]
1066
+ when TASK_TIME_TRIGGER_DAILY
1067
+ tmp = {}
1068
+ tmp['days_interval'] = [tr[14]].pack('L').unpack('SS').first
1069
+ trigger['type'] = tmp
1070
+ when TASK_TIME_TRIGGER_WEEKLY
1071
+ tmp = {}
1072
+ tmp['weeks_interval'],tmp['days_of_week'] = [tr[14]].pack('L').unpack('SS')
1073
+ trigger['type'] = tmp
1074
+ when TASK_TIME_TRIGGER_MONTHLYDATE
1075
+ tmp = {}
1076
+ tmp['days'] = tr[14]
1077
+ tmp['months'] = [tr[15]].pack('L').unpack('SS').first
1078
+ trigger['type'] = tmp
1079
+ when TASK_TIME_TRIGGER_MONTHLYDOW
1080
+ tmp = {}
1081
+ tmp['weeks'],tmp['days_of_week'] = [tr[14]].pack('L').unpack('SS')
1082
+ tmp['months'] = [tr[15]].pack('L').unpack('SS').first
1083
+ trigger['type'] = tmp
1084
+ when TASK_TIME_TRIGGER_ONCE
1085
+ tmp = {}
1086
+ tmp['once'] = nil
1087
+ trigger['type'] = tmp
1088
+ else
1089
+ raise Error, 'Unknown trigger type'
1280
1090
  end
1281
1091
 
1282
- # Returns the flags (integer) that modify the behavior of the work item. You
1283
- # must OR the return value to determine the flags yourself.
1284
- #
1285
- def flags
1286
- raise Error, 'null pointer' if @pITask.nil?
1092
+ release.call(pITaskTrigger)
1093
+
1094
+ trigger
1095
+ end
1096
+
1097
+ # Sets the trigger for the currently active task.
1098
+ #
1099
+ def trigger=(trigger)
1100
+ raise Error, 'null pointer' if @pITS.nil?
1101
+ raise Error, 'No currently active task' if @pITask.nil?
1102
+ raise TypeError unless trigger.is_a?(Hash)
1103
+
1104
+ trigger = transform_and_validate(trigger)
1105
+
1106
+ lpVtbl = 0.chr * 4
1107
+ table = 0.chr * 16
1108
+
1109
+ memcpy(lpVtbl, @pITask, 4)
1110
+ memcpy(table, lpVtbl.unpack('L').first, 16)
1111
+ table = table.unpack('L*')
1112
+
1113
+ createTrigger = Win32::API::Function.new(table[3], 'PPP', 'L')
1287
1114
 
1288
- lpVtbl = 0.chr * 4
1289
- table = 0.chr * 120
1115
+ p1 = 0.chr * 4
1116
+ p2 = 0.chr * 4
1290
1117
 
1291
- memcpy(lpVtbl, @pITask, 4)
1292
- memcpy(table, lpVtbl.unpack('L').first, 120)
1293
- table = table.unpack('L*')
1118
+ hr = createTrigger.call(@pITask, p1, p2)
1294
1119
 
1295
- getFlags = Win32::API::Function.new(table[29], 'PP', 'L')
1296
- ptr = 0.chr * 4
1297
- hr = getFlags.call(@pITask, ptr)
1120
+ if hr != S_OK
1121
+ raise Error, get_last_error
1122
+ end
1298
1123
 
1299
- if hr != S_OK
1300
- raise Error, get_last_error
1301
- end
1124
+ pITaskTrigger = p2.unpack('L').first
1125
+ lpVtbl = 0.chr * 4
1126
+ table = 0.chr * 16
1127
+
1128
+ memcpy(lpVtbl, pITaskTrigger, 4)
1129
+ memcpy(table, lpVtbl.unpack('L').first, 16)
1130
+ table = table.unpack('L*')
1131
+
1132
+ release = Win32::API::Function.new(table[2], 'P', 'L')
1133
+ setTrigger = Win32::API::Function.new(table[3], 'PP', 'L')
1134
+
1135
+ type1 = 0
1136
+ type2 = 0
1137
+ tmp = trigger['type']
1138
+ tmp = nil unless tmp.is_a?(Hash)
1139
+
1140
+ case trigger['trigger_type']
1141
+ when TASK_TIME_TRIGGER_DAILY
1142
+ if tmp && tmp['days_interval']
1143
+ type1 = [tmp['days_interval'],0].pack('SS').unpack('L').first
1144
+ end
1145
+ when TASK_TIME_TRIGGER_WEEKLY
1146
+ if tmp && tmp['weeks_interval'] && tmp['days_of_week']
1147
+ type1 = [tmp['weeks_interval'],tmp['days_of_week']].pack('SS').unpack('L').first
1148
+ end
1149
+ when TASK_TIME_TRIGGER_MONTHLYDATE
1150
+ if tmp && tmp['months'] && tmp['days']
1151
+ type2 = [tmp['months'],0].pack('SS').unpack('L').first
1152
+ type1 = tmp['days']
1153
+ end
1154
+ when TASK_TIME_TRIGGER_MONTHLYDOW
1155
+ if tmp && tmp['weeks'] && tmp['days_of_week'] && tmp['months']
1156
+ type1 = [tmp['weeks'],tmp['days_of_week']].pack('SS').unpack('L').first
1157
+ type2 = [tmp['months'],0].pack('SS').unpack('L').first
1158
+ end
1159
+ when TASK_TIME_TRIGGER_ONCE
1160
+ # Do nothing. The Type member of the TASK_TRIGGER struct is ignored.
1161
+ else
1162
+ raise Error, 'Unknown trigger type'
1163
+ end
1302
1164
 
1303
- flags = ptr.unpack('L').first
1165
+ pTrigger = [
1166
+ 48,
1167
+ 0,
1168
+ trigger['start_year'] || 0,
1169
+ trigger['start_month'] || 0,
1170
+ trigger['start_day'] || 0,
1171
+ trigger['end_year'] || 0,
1172
+ trigger['end_month'] || 0,
1173
+ trigger['end_day'] || 0,
1174
+ trigger['start_hour'] || 0,
1175
+ trigger['start_minute'] || 0,
1176
+ trigger['minutes_duration'] || 0,
1177
+ trigger['minutes_interval'] || 0,
1178
+ trigger['flags'] || 0,
1179
+ trigger['trigger_type'] || 0,
1180
+ type1,
1181
+ type2,
1182
+ 0,
1183
+ trigger['random_minutes_interval'] || 0
1184
+ ].pack('S10L4LLSS')
1185
+
1186
+ hr = setTrigger.call(pITaskTrigger, pTrigger)
1187
+
1188
+ if hr != S_OK
1189
+ raise Error, get_last_error
1304
1190
  end
1305
1191
 
1306
- # Sets an OR'd value of flags that modify the behavior of the work item.
1307
- #
1308
- def flags=(flags)
1309
- raise Error, 'null pointer' if @pITS.nil?
1310
- raise Error, 'No currently active task' if @pITask.nil?
1192
+ release.call(pITaskTrigger)
1193
+
1194
+ trigger
1195
+ end
1311
1196
 
1312
- lpVtbl = 0.chr * 4
1313
- table = 0.chr * 116
1197
+ # Adds a trigger at the specified index.
1198
+ #
1199
+ def add_trigger(index, trigger)
1200
+ raise Error, 'null pointer' if @pITS.nil?
1201
+ raise Error, 'No currently active task' if @pITask.nil?
1202
+ raise TypeError unless trigger.is_a?(Hash)
1314
1203
 
1315
- memcpy(lpVtbl, @pITask, 4)
1316
- memcpy(table, lpVtbl.unpack('L').first, 116)
1317
- table = table.unpack('L*')
1204
+ trigger = transform_and_validate(trigger)
1318
1205
 
1319
- setFlags = Win32::API::Function.new(table[28], 'PL', 'L')
1320
- hr = setFlags.call(@pITask, flags)
1206
+ lpVtbl = 0.chr * 4
1207
+ table = 0.chr * 28
1321
1208
 
1322
- if hr != S_OK
1323
- raise Error, get_last_error
1324
- end
1209
+ memcpy(lpVtbl, @pITask, 4)
1210
+ memcpy(table, lpVtbl.unpack('L').first, 28)
1211
+ table = table.unpack('L*')
1325
1212
 
1326
- flags
1213
+ getTrigger = Win32::API::Function.new(table[6], 'PLP', 'L')
1214
+ ptr = 0.chr * 4
1215
+ hr = getTrigger.call(@pITask, index, ptr)
1216
+
1217
+ if hr != S_OK
1218
+ raise Error, get_last_error
1327
1219
  end
1328
1220
 
1329
- # Returns the status of the currently active task. Possible values are
1330
- # 'ready', 'running', 'not scheduled' or 'unknown'.
1331
- #
1332
- def status
1333
- raise Error, 'null pointer' if @pITask.nil?
1334
- raise Error, 'No currently active task' if @pITask.nil?
1335
-
1336
- lpVtbl = 0.chr * 4
1337
- table = 0.chr * 68
1338
-
1339
- memcpy(lpVtbl,@pITask,4)
1340
- memcpy(table,lpVtbl.unpack('L').first,68)
1341
- table = table.unpack('L*')
1342
-
1343
- getStatus = Win32::API::Function.new(table[16], 'PP', 'L')
1344
- ptr = 0.chr * 4
1345
- hr = getStatus.call(@pITask, ptr)
1346
-
1347
- if hr != S_OK
1348
- raise Error,get_last_error
1349
- end
1350
-
1351
- st = ptr.unpack('L').first
1352
-
1353
- case st
1354
- when 0x00041300 # SCHED_S_TASK_READY
1355
- status = 'ready'
1356
- when 0x00041301 # SCHED_S_TASK_RUNNING
1357
- status = 'running'
1358
- when 0x00041305 # SCHED_S_TASK_NOT_SCHEDULED
1359
- status = 'not scheduled'
1360
- else
1361
- status = 'unknown'
1362
- end
1221
+ pITaskTrigger = ptr.unpack('L').first
1222
+ lpVtbl = 0.chr * 4
1223
+ table = 0.chr * 16
1224
+
1225
+ memcpy(lpVtbl, pITaskTrigger,4)
1226
+ memcpy(table, lpVtbl.unpack('L').first,16)
1227
+ table = table.unpack('L*')
1228
+
1229
+ release = Win32::API::Function.new(table[2], 'P', 'L')
1230
+ setTrigger = Win32::API::Function.new(table[3], 'PP', 'L')
1231
+
1232
+ type1 = 0
1233
+ type2 = 0
1234
+ tmp = trigger['type']
1235
+ tmp = nil unless tmp.is_a?(Hash)
1236
+
1237
+ case trigger['trigger_type']
1238
+ when TASK_TIME_TRIGGER_DAILY
1239
+ if tmp && tmp['days_interval']
1240
+ type1 = [tmp['days_interval'],0].pack('SS').unpack('L').first
1241
+ end
1242
+ when TASK_TIME_TRIGGER_WEEKLY
1243
+ if tmp && tmp['weeks_interval'] && tmp['days_of_week']
1244
+ type1 = [tmp['weeks_interval'],tmp['days_of_week']].pack('SS').unpack('L').first
1245
+ end
1246
+ when TASK_TIME_TRIGGER_MONTHLYDATE
1247
+ if tmp && tmp['months'] && tmp['days']
1248
+ type2 = [tmp['months'],0].pack('SS').unpack('L').first
1249
+ type1 = tmp['days']
1250
+ end
1251
+ when TASK_TIME_TRIGGER_MONTHLYDOW
1252
+ if tmp && tmp['weeks'] && tmp['days_of_week'] && tmp['months']
1253
+ type1 = [tmp['weeks'],tmp['days_of_week']].pack('SS').unpack('L').first
1254
+ type2 = [tmp['months'],0].pack('SS').unpack('L').first
1255
+ end
1256
+ when TASK_TIME_TRIGGER_ONCE
1257
+ # Do nothing. The Type member of the TASK_TRIGGER struct is ignored.
1258
+ else
1259
+ raise Error, 'Unknown trigger type'
1260
+ end
1363
1261
 
1364
- status
1262
+ pTrigger = [
1263
+ 48,
1264
+ 0,
1265
+ trigger['start_year'] || 0,
1266
+ trigger['start_month'] || 0,
1267
+ trigger['start_day'] || 0,
1268
+ trigger['end_year'] || 0,
1269
+ trigger['end_month'] || 0,
1270
+ trigger['end_day'] || 0,
1271
+ trigger['start_hour'] || 0,
1272
+ trigger['start_minute'] || 0,
1273
+ trigger['minutes_duration'] || 0,
1274
+ trigger['minutes_interval'] || 0,
1275
+ trigger['flags'] || 0,
1276
+ trigger['trigger_type'] || 0,
1277
+ type1,
1278
+ type2,
1279
+ 0,
1280
+ trigger['random_minutes_interval'] || 0
1281
+ ].pack('S10L4LLSS')
1282
+
1283
+ hr = setTrigger.call(pITaskTrigger, pTrigger)
1284
+
1285
+ if hr != S_OK
1286
+ raise Error, get_last_error
1365
1287
  end
1366
1288
 
1367
- # Returns the exit code from the last scheduled run.
1368
- #
1369
- def exit_code
1370
- raise Error, 'null pointer' if @pITask.nil?
1371
- raise Error, 'No currently active task' if @pITask.nil?
1289
+ release.call(pITaskTrigger)
1290
+ end
1372
1291
 
1373
- lpVtbl = 0.chr * 4
1374
- table = 0.chr * 72
1292
+ # Returns the flags (integer) that modify the behavior of the work item. You
1293
+ # must OR the return value to determine the flags yourself.
1294
+ #
1295
+ def flags
1296
+ raise Error, 'null pointer' if @pITask.nil?
1375
1297
 
1376
- memcpy(lpVtbl, @pITask, 4)
1377
- memcpy(table, lpVtbl.unpack('L').first, 72)
1378
- table = table.unpack('L*')
1298
+ lpVtbl = 0.chr * 4
1299
+ table = 0.chr * 120
1379
1300
 
1380
- getExitCode = Win32::API::Function.new(table[17], 'PP', 'L')
1381
- ptr = 0.chr * 4
1382
- hr = getExitCode.call(@pITask, ptr)
1301
+ memcpy(lpVtbl, @pITask, 4)
1302
+ memcpy(table, lpVtbl.unpack('L').first, 120)
1303
+ table = table.unpack('L*')
1383
1304
 
1384
- if hr > 0x80000000
1385
- raise Error, get_last_error
1386
- end
1305
+ getFlags = Win32::API::Function.new(table[29], 'PP', 'L')
1306
+ ptr = 0.chr * 4
1307
+ hr = getFlags.call(@pITask, ptr)
1387
1308
 
1388
- exit_code = ptr.unpack('L').first
1309
+ if hr != S_OK
1310
+ raise Error, get_last_error
1389
1311
  end
1390
1312
 
1391
- # Returns the comment associated with the task, if any.
1392
- #
1393
- def comment
1394
- raise Error, 'null pointer' if @pITask.nil?
1395
- raise Error, 'No currently active task' if @pITask.nil?
1313
+ flags = ptr.unpack('L').first
1314
+ end
1396
1315
 
1397
- lpVtbl = 0.chr * 4
1398
- table = 0.chr * 80
1316
+ # Sets an OR'd value of flags that modify the behavior of the work item.
1317
+ #
1318
+ def flags=(flags)
1319
+ raise Error, 'null pointer' if @pITS.nil?
1320
+ raise Error, 'No currently active task' if @pITask.nil?
1399
1321
 
1400
- memcpy(lpVtbl, @pITask, 4)
1401
- memcpy(table, lpVtbl.unpack('L').first, 80)
1402
- table = table.unpack('L*')
1322
+ lpVtbl = 0.chr * 4
1323
+ table = 0.chr * 116
1403
1324
 
1404
- getComment = Win32::API::Function.new(table[19], 'PP', 'L')
1405
- ptr = 0.chr * 4
1406
- hr = getComment.call(@pITask, ptr)
1325
+ memcpy(lpVtbl, @pITask, 4)
1326
+ memcpy(table, lpVtbl.unpack('L').first, 116)
1327
+ table = table.unpack('L*')
1407
1328
 
1408
- if hr != S_OK
1409
- raise Error,get_last_error
1410
- end
1329
+ setFlags = Win32::API::Function.new(table[28], 'PL', 'L')
1330
+ hr = setFlags.call(@pITask, flags)
1411
1331
 
1412
- str = 0.chr * 256
1413
- wcscpy(str, ptr.unpack('L').first)
1414
- CoTaskMemFree(ptr.unpack('L').first)
1415
- wide_to_multi(str)
1332
+ if hr != S_OK
1333
+ raise Error, get_last_error
1416
1334
  end
1417
1335
 
1418
- # Sets the comment for the task.
1419
- #
1420
- def comment=(comment)
1421
- raise Error, 'null pointer' if @pITask.nil?
1422
- raise Error, 'No currently active task' if @pITask.nil?
1423
- raise TypeError unless comment.is_a?(String)
1336
+ flags
1337
+ end
1338
+
1339
+ # Returns the status of the currently active task. Possible values are
1340
+ # 'ready', 'running', 'not scheduled' or 'unknown'.
1341
+ #
1342
+ def status
1343
+ raise Error, 'null pointer' if @pITask.nil?
1344
+ raise Error, 'No currently active task' if @pITask.nil?
1424
1345
 
1425
- lpVtbl = 0.chr * 4
1426
- table = 0.chr * 76
1346
+ lpVtbl = 0.chr * 4
1347
+ table = 0.chr * 68
1427
1348
 
1428
- memcpy(lpVtbl, @pITask, 4)
1429
- memcpy(table, lpVtbl.unpack('L').first, 76)
1430
- table = table.unpack('L*')
1349
+ memcpy(lpVtbl,@pITask,4)
1350
+ memcpy(table,lpVtbl.unpack('L').first,68)
1351
+ table = table.unpack('L*')
1431
1352
 
1432
- setComment = Win32::API::Function.new(table[18], 'PP', 'L')
1433
- comment_w = multi_to_wide(comment)
1434
- hr = setComment.call(@pITask, comment_w)
1353
+ getStatus = Win32::API::Function.new(table[16], 'PP', 'L')
1354
+ ptr = 0.chr * 4
1355
+ hr = getStatus.call(@pITask, ptr)
1435
1356
 
1436
- if hr != S_OK
1437
- raise Error, get_last_error
1438
- end
1357
+ if hr != S_OK
1358
+ raise Error,get_last_error
1359
+ end
1439
1360
 
1440
- comment
1361
+ st = ptr.unpack('L').first
1362
+
1363
+ case st
1364
+ when 0x00041300 # SCHED_S_TASK_READY
1365
+ status = 'ready'
1366
+ when 0x00041301 # SCHED_S_TASK_RUNNING
1367
+ status = 'running'
1368
+ when 0x00041305 # SCHED_S_TASK_NOT_SCHEDULED
1369
+ status = 'not scheduled'
1370
+ else
1371
+ status = 'unknown'
1441
1372
  end
1442
1373
 
1443
- # Returns the name of the user who created the task.
1444
- #
1445
- def creator
1446
- raise Error, 'null pointer' if @pITask.nil?
1447
- raise Error, 'No currently active task' if @pITask.nil?
1374
+ status
1375
+ end
1448
1376
 
1449
- lpVtbl = 0.chr * 4
1450
- table = 0.chr * 88
1377
+ # Returns the exit code from the last scheduled run.
1378
+ #
1379
+ def exit_code
1380
+ raise Error, 'null pointer' if @pITask.nil?
1381
+ raise Error, 'No currently active task' if @pITask.nil?
1451
1382
 
1452
- memcpy(lpVtbl, @pITask, 4)
1453
- memcpy(table, lpVtbl.unpack('L').first, 88)
1454
- table = table.unpack('L*')
1383
+ lpVtbl = 0.chr * 4
1384
+ table = 0.chr * 72
1455
1385
 
1456
- getCreator = Win32::API::Function.new(table[21], 'PP', 'L')
1457
- ptr = 0.chr * 4
1458
- hr = getCreator.call(@pITask, ptr)
1386
+ memcpy(lpVtbl, @pITask, 4)
1387
+ memcpy(table, lpVtbl.unpack('L').first, 72)
1388
+ table = table.unpack('L*')
1459
1389
 
1460
- if hr != S_OK
1461
- raise Error, get_last_error
1462
- end
1390
+ getExitCode = Win32::API::Function.new(table[17], 'PP', 'L')
1391
+ ptr = 0.chr * 4
1392
+ hr = getExitCode.call(@pITask, ptr)
1463
1393
 
1464
- str = 0.chr * 256
1465
- wcscpy(str, ptr.unpack('L').first)
1466
- CoTaskMemFree(ptr.unpack('L').first)
1467
- wide_to_multi(str)
1394
+ if hr > 0x80000000
1395
+ raise Error, get_last_error
1468
1396
  end
1469
1397
 
1470
- # Sets the creator for the task.
1471
- #
1472
- def creator=(creator)
1473
- raise Error, 'null pointer' if @pITask.nil?
1474
- raise Error, 'No currently active task' if @pITask.nil?
1475
- raise TypeError unless creator.is_a?(String)
1398
+ ptr.unpack('L').first
1399
+ end
1476
1400
 
1477
- lpVtbl = 0.chr * 4
1478
- table = 0.chr * 84
1401
+ # Returns the comment associated with the task, if any.
1402
+ #
1403
+ def comment
1404
+ raise Error, 'null pointer' if @pITask.nil?
1405
+ raise Error, 'No currently active task' if @pITask.nil?
1479
1406
 
1480
- memcpy(lpVtbl, @pITask, 4)
1481
- memcpy(table, lpVtbl.unpack('L').first, 84)
1482
- table = table.unpack('L*')
1407
+ lpVtbl = 0.chr * 4
1408
+ table = 0.chr * 80
1483
1409
 
1484
- setCreator = Win32::API::Function.new(table[20], 'PP', 'L')
1485
- creator_w = multi_to_wide(creator)
1486
- hr = setCreator.call(@pITask, creator_w)
1410
+ memcpy(lpVtbl, @pITask, 4)
1411
+ memcpy(table, lpVtbl.unpack('L').first, 80)
1412
+ table = table.unpack('L*')
1487
1413
 
1488
- if hr != S_OK
1489
- raise Error, get_last_error
1490
- end
1414
+ getComment = Win32::API::Function.new(table[19], 'PP', 'L')
1415
+ ptr = 0.chr * 4
1416
+ hr = getComment.call(@pITask, ptr)
1491
1417
 
1492
- creator
1418
+ if hr != S_OK
1419
+ raise Error,get_last_error
1493
1420
  end
1494
1421
 
1495
- # Returns a Time object that indicates the next time the task will run.
1496
- #
1497
- def next_run_time
1498
- raise Error, 'null pointer' if @pITask.nil?
1499
- raise Error, 'No currently active task' if @pITask.nil?
1422
+ str = 0.chr * 256
1423
+ wcscpy(str, ptr.unpack('L').first)
1424
+ CoTaskMemFree(ptr.unpack('L').first)
1425
+ wide_to_multi(str)
1426
+ end
1427
+
1428
+ # Sets the comment for the task.
1429
+ #
1430
+ def comment=(comment)
1431
+ raise Error, 'null pointer' if @pITask.nil?
1432
+ raise Error, 'No currently active task' if @pITask.nil?
1433
+ raise TypeError unless comment.is_a?(String)
1434
+
1435
+ lpVtbl = 0.chr * 4
1436
+ table = 0.chr * 76
1437
+
1438
+ memcpy(lpVtbl, @pITask, 4)
1439
+ memcpy(table, lpVtbl.unpack('L').first, 76)
1440
+ table = table.unpack('L*')
1500
1441
 
1501
- lpVtbl = 0.chr * 4
1502
- table = 0.chr * 40
1442
+ setComment = Win32::API::Function.new(table[18], 'PP', 'L')
1443
+ comment_w = multi_to_wide(comment)
1444
+ hr = setComment.call(@pITask, comment_w)
1503
1445
 
1504
- memcpy(lpVtbl, @pITask, 4)
1505
- memcpy(table, lpVtbl.unpack('L').first, 40)
1506
- table = table.unpack('L*')
1446
+ if hr != S_OK
1447
+ raise Error, get_last_error
1448
+ end
1449
+
1450
+ comment
1451
+ end
1452
+
1453
+ # Returns the name of the user who created the task.
1454
+ #
1455
+ def creator
1456
+ raise Error, 'null pointer' if @pITask.nil?
1457
+ raise Error, 'No currently active task' if @pITask.nil?
1507
1458
 
1508
- getNextRunTime = Win32::API::Function.new(table[9], 'PP', 'L')
1509
- st = 0.chr * 16
1510
- hr = getNextRunTime.call(@pITask, st)
1459
+ lpVtbl = 0.chr * 4
1460
+ table = 0.chr * 88
1511
1461
 
1512
- if hr != S_OK
1513
- raise Error, get_last_error
1514
- end
1462
+ memcpy(lpVtbl, @pITask, 4)
1463
+ memcpy(table, lpVtbl.unpack('L').first, 88)
1464
+ table = table.unpack('L*')
1515
1465
 
1516
- a1,a2,_,a3,a4,a5,a6,a7 = st.unpack('S*')
1517
- a7 *= 1000
1466
+ getCreator = Win32::API::Function.new(table[21], 'PP', 'L')
1467
+ ptr = 0.chr * 4
1468
+ hr = getCreator.call(@pITask, ptr)
1518
1469
 
1519
- Time.local(a1,a2,a3,a4,a5,a6,a7)
1470
+ if hr != S_OK
1471
+ raise Error, get_last_error
1520
1472
  end
1521
1473
 
1522
- # Returns a Time object indicating the most recent time the task ran or
1523
- # nil if the task has never run.
1524
- #
1525
- def most_recent_run_time
1526
- raise Error, 'null pointer' if @pITask.nil?
1527
- raise Error, 'No currently active task' if @pITask.nil?
1528
-
1529
- lpVtbl = 0.chr * 4
1530
- table = 0.chr * 64
1531
-
1532
- memcpy(lpVtbl, @pITask, 4)
1533
- memcpy(table, lpVtbl.unpack('L').first, 64)
1534
- table = table.unpack('L*')
1535
-
1536
- getMostRecentRunTime = Win32::API::Function.new(table[15], 'PP', 'L')
1537
- st = 0.chr * 16
1538
- hr = getMostRecentRunTime.call(@pITask, st)
1539
-
1540
- if hr == 0x00041303 # SCHED_S_TASK_HAS_NOT_RUN
1541
- time = nil
1542
- elsif hr == S_OK
1543
- a1, a2, _, a3, a4, a5, a6, a7 = st.unpack('S*')
1544
- a7 *= 1000
1545
- time = Time.local(a1, a2, a3, a4, a5, a6, a7)
1546
- else
1547
- raise Error, get_last_error
1548
- end
1549
-
1550
- time
1474
+ str = 0.chr * 256
1475
+ wcscpy(str, ptr.unpack('L').first)
1476
+ CoTaskMemFree(ptr.unpack('L').first)
1477
+ wide_to_multi(str)
1478
+ end
1479
+
1480
+ # Sets the creator for the task.
1481
+ #
1482
+ def creator=(creator)
1483
+ raise Error, 'null pointer' if @pITask.nil?
1484
+ raise Error, 'No currently active task' if @pITask.nil?
1485
+ raise TypeError unless creator.is_a?(String)
1486
+
1487
+ lpVtbl = 0.chr * 4
1488
+ table = 0.chr * 84
1489
+
1490
+ memcpy(lpVtbl, @pITask, 4)
1491
+ memcpy(table, lpVtbl.unpack('L').first, 84)
1492
+ table = table.unpack('L*')
1493
+
1494
+ setCreator = Win32::API::Function.new(table[20], 'PP', 'L')
1495
+ creator_w = multi_to_wide(creator)
1496
+ hr = setCreator.call(@pITask, creator_w)
1497
+
1498
+ if hr != S_OK
1499
+ raise Error, get_last_error
1551
1500
  end
1552
1501
 
1553
- # Returns the maximum length of time, in milliseconds, that the task
1554
- # will run before terminating.
1555
- #
1556
- def max_run_time
1557
- raise Error, 'null pointer' if @pITask.nil?
1558
- raise Error, 'No currently active task' if @pITask.nil?
1502
+ creator
1503
+ end
1559
1504
 
1560
- lpVtbl = 0.chr * 4
1561
- table = 0.chr * 176
1505
+ # Returns a Time object that indicates the next time the task will run.
1506
+ #
1507
+ def next_run_time
1508
+ raise Error, 'null pointer' if @pITask.nil?
1509
+ raise Error, 'No currently active task' if @pITask.nil?
1562
1510
 
1563
- memcpy(lpVtbl, @pITask, 4)
1564
- memcpy(table, lpVtbl.unpack('L').first, 176)
1565
- table = table.unpack('L*')
1511
+ lpVtbl = 0.chr * 4
1512
+ table = 0.chr * 40
1566
1513
 
1567
- getMaxRunTime = Win32::API::Function.new(table[43], 'PP', 'L')
1514
+ memcpy(lpVtbl, @pITask, 4)
1515
+ memcpy(table, lpVtbl.unpack('L').first, 40)
1516
+ table = table.unpack('L*')
1568
1517
 
1569
- ptr = 0.chr * 4
1570
- hr = getMaxRunTime.call(@pITask, ptr)
1518
+ getNextRunTime = Win32::API::Function.new(table[9], 'PP', 'L')
1519
+ st = 0.chr * 16
1520
+ hr = getNextRunTime.call(@pITask, st)
1571
1521
 
1572
- if hr != S_OK
1573
- raise Error, get_last_error
1574
- end
1522
+ if hr != S_OK
1523
+ raise Error, get_last_error
1524
+ end
1575
1525
 
1576
- max_run_time = ptr.unpack('L').first
1526
+ a1,a2,_,a3,a4,a5,a6,a7 = st.unpack('S*')
1527
+ a7 *= 1000
1528
+
1529
+ Time.local(a1,a2,a3,a4,a5,a6,a7)
1530
+ end
1531
+
1532
+ # Returns a Time object indicating the most recent time the task ran or
1533
+ # nil if the task has never run.
1534
+ #
1535
+ def most_recent_run_time
1536
+ raise Error, 'null pointer' if @pITask.nil?
1537
+ raise Error, 'No currently active task' if @pITask.nil?
1538
+
1539
+ lpVtbl = 0.chr * 4
1540
+ table = 0.chr * 64
1541
+
1542
+ memcpy(lpVtbl, @pITask, 4)
1543
+ memcpy(table, lpVtbl.unpack('L').first, 64)
1544
+ table = table.unpack('L*')
1545
+
1546
+ getMostRecentRunTime = Win32::API::Function.new(table[15], 'PP', 'L')
1547
+ st = 0.chr * 16
1548
+ hr = getMostRecentRunTime.call(@pITask, st)
1549
+
1550
+ if hr == 0x00041303 # SCHED_S_TASK_HAS_NOT_RUN
1551
+ time = nil
1552
+ elsif hr == S_OK
1553
+ a1, a2, _, a3, a4, a5, a6, a7 = st.unpack('S*')
1554
+ a7 *= 1000
1555
+ time = Time.local(a1, a2, a3, a4, a5, a6, a7)
1556
+ else
1557
+ raise Error, get_last_error
1577
1558
  end
1578
1559
 
1579
- # Sets the maximum length of time, in milliseconds, that the task can run
1580
- # before terminating. Returns the value you specified if successful.
1581
- #
1582
- def max_run_time=(max_run_time)
1583
- raise Error, 'null pointer' if @pITask.nil?
1584
- raise Error, 'No currently active task' if @pITask.nil?
1585
- raise TypeError unless max_run_time.is_a?(Numeric)
1586
-
1587
- lpVtbl = 0.chr * 4
1588
- table = 0.chr * 172
1589
-
1590
- memcpy(lpVtbl, @pITask, 4)
1591
- memcpy(table, lpVtbl.unpack('L').first, 172)
1592
- table = table.unpack('L*')
1593
-
1594
- setMaxRunTime = Win32::API::Function.new(table[42], 'PL', 'L')
1595
- hr = setMaxRunTime.call(@pITask, max_run_time)
1596
-
1597
- if hr != S_OK
1598
- raise Error,get_last_error
1599
- end
1600
-
1601
- max_run_time
1560
+ time
1561
+ end
1562
+
1563
+ # Returns the maximum length of time, in milliseconds, that the task
1564
+ # will run before terminating.
1565
+ #
1566
+ def max_run_time
1567
+ raise Error, 'null pointer' if @pITask.nil?
1568
+ raise Error, 'No currently active task' if @pITask.nil?
1569
+
1570
+ lpVtbl = 0.chr * 4
1571
+ table = 0.chr * 176
1572
+
1573
+ memcpy(lpVtbl, @pITask, 4)
1574
+ memcpy(table, lpVtbl.unpack('L').first, 176)
1575
+ table = table.unpack('L*')
1576
+
1577
+ getMaxRunTime = Win32::API::Function.new(table[43], 'PP', 'L')
1578
+
1579
+ ptr = 0.chr * 4
1580
+ hr = getMaxRunTime.call(@pITask, ptr)
1581
+
1582
+ if hr != S_OK
1583
+ raise Error, get_last_error
1602
1584
  end
1603
-
1604
- # Returns whether or not the scheduled task exists.
1605
- def exists?(job_name)
1606
- bool = false
1607
- Dir.foreach('C:/Windows/Tasks'){ |file|
1608
- if File.basename(file, '.job') == job_name
1609
- bool = true
1610
- break
1611
- end
1612
- }
1613
- bool
1585
+
1586
+ max_run_time = ptr.unpack('L').first
1587
+ end
1588
+
1589
+ # Sets the maximum length of time, in milliseconds, that the task can run
1590
+ # before terminating. Returns the value you specified if successful.
1591
+ #
1592
+ def max_run_time=(max_run_time)
1593
+ raise Error, 'null pointer' if @pITask.nil?
1594
+ raise Error, 'No currently active task' if @pITask.nil?
1595
+ raise TypeError unless max_run_time.is_a?(Numeric)
1596
+
1597
+ lpVtbl = 0.chr * 4
1598
+ table = 0.chr * 172
1599
+
1600
+ memcpy(lpVtbl, @pITask, 4)
1601
+ memcpy(table, lpVtbl.unpack('L').first, 172)
1602
+ table = table.unpack('L*')
1603
+
1604
+ setMaxRunTime = Win32::API::Function.new(table[42], 'PL', 'L')
1605
+ hr = setMaxRunTime.call(@pITask, max_run_time)
1606
+
1607
+ if hr != S_OK
1608
+ raise Error,get_last_error
1614
1609
  end
1615
1610
 
1616
- private
1617
-
1618
- # Used for the new_work_item method
1619
- ValidTriggerKeys = [
1620
- 'end_day',
1621
- 'end_month',
1622
- 'end_year',
1623
- 'flags',
1624
- 'minutes_duration',
1625
- 'minutes_interval',
1626
- 'random_minutes_interval',
1627
- 'start_day',
1628
- 'start_hour',
1629
- 'start_minute',
1630
- 'start_month',
1631
- 'start_year',
1632
- 'trigger_type',
1633
- 'type'
1634
- ]
1635
-
1636
- ValidTypeKeys = [
1637
- 'days_interval',
1638
- 'weeks_interval',
1639
- 'days_of_week',
1640
- 'months',
1641
- 'days',
1642
- 'weeks'
1643
- ]
1644
-
1645
- # Private method that validates keys, and converts all keys to lowercase
1646
- # strings.
1647
- #
1648
- def transform_and_validate(hash)
1649
- new_hash = {}
1650
-
1651
- hash.each{ |key, value|
1652
- key = key.to_s.downcase
1653
- if key == 'type'
1654
- new_type_hash = {}
1655
- raise ArgumentError unless value.is_a?(Hash)
1656
- value.each{ |subkey, subvalue|
1657
- subkey = subkey.to_s.downcase
1658
- if ValidTypeKeys.include?(subkey)
1659
- new_type_hash[subkey] = subvalue
1660
- else
1661
- raise ArgumentError, "Invalid type key '#{subkey}'"
1662
- end
1663
- }
1664
- new_hash[key] = new_type_hash
1611
+ max_run_time
1612
+ end
1613
+
1614
+ # Returns whether or not the scheduled task exists.
1615
+ def exists?(job_name)
1616
+ bool = false
1617
+ Dir.foreach('C:/Windows/Tasks'){ |file|
1618
+ if File.basename(file, '.job') == job_name
1619
+ bool = true
1620
+ break
1621
+ end
1622
+ }
1623
+ bool
1624
+ end
1625
+
1626
+ private
1627
+
1628
+ # :stopdoc:
1629
+
1630
+ # Used for the new_work_item method
1631
+ ValidTriggerKeys = [
1632
+ 'end_day',
1633
+ 'end_month',
1634
+ 'end_year',
1635
+ 'flags',
1636
+ 'minutes_duration',
1637
+ 'minutes_interval',
1638
+ 'random_minutes_interval',
1639
+ 'start_day',
1640
+ 'start_hour',
1641
+ 'start_minute',
1642
+ 'start_month',
1643
+ 'start_year',
1644
+ 'trigger_type',
1645
+ 'type'
1646
+ ]
1647
+
1648
+ ValidTypeKeys = [
1649
+ 'days_interval',
1650
+ 'weeks_interval',
1651
+ 'days_of_week',
1652
+ 'months',
1653
+ 'days',
1654
+ 'weeks'
1655
+ ]
1656
+
1657
+ # Private method that validates keys, and converts all keys to lowercase
1658
+ # strings.
1659
+ #
1660
+ def transform_and_validate(hash)
1661
+ new_hash = {}
1662
+
1663
+ hash.each{ |key, value|
1664
+ key = key.to_s.downcase
1665
+ if key == 'type'
1666
+ new_type_hash = {}
1667
+ raise ArgumentError unless value.is_a?(Hash)
1668
+ value.each{ |subkey, subvalue|
1669
+ subkey = subkey.to_s.downcase
1670
+ if ValidTypeKeys.include?(subkey)
1671
+ new_type_hash[subkey] = subvalue
1665
1672
  else
1666
- if ValidTriggerKeys.include?(key)
1667
- new_hash[key] = value
1668
- else
1669
- raise ArgumentError, "Invalid key '#{key}'"
1670
- end
1673
+ raise ArgumentError, "Invalid type key '#{subkey}'"
1671
1674
  end
1672
- }
1673
-
1674
- new_hash
1675
- end
1676
- end
1675
+ }
1676
+ new_hash[key] = new_type_hash
1677
+ else
1678
+ if ValidTriggerKeys.include?(key)
1679
+ new_hash[key] = value
1680
+ else
1681
+ raise ArgumentError, "Invalid key '#{key}'"
1682
+ end
1683
+ end
1684
+ }
1685
+
1686
+ new_hash
1687
+ end
1688
+ end
1677
1689
  end