win32-taskscheduler 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGES 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