forked from capnspacehook/taskmaster
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtasks.go
181 lines (148 loc) · 5.6 KB
/
tasks.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// +build windows
package taskmaster
import (
"errors"
"fmt"
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
func (d *Definition) AddAction(action Action) {
d.Actions = append(d.Actions, action)
}
func (d *Definition) AddTrigger(trigger Trigger) {
d.Triggers = append(d.Triggers, trigger)
}
// Refresh refreshes all of the local instance variables of the running task.
// https://docs.microsoft.com/en-us/windows/desktop/api/taskschd/nf-taskschd-irunningtask-refresh
func (r RunningTask) Refresh() error {
_, err := oleutil.CallMethod(r.taskObj, "Refresh")
if err != nil {
return fmt.Errorf("error refreshing running task %s: %v", r.Path, getTaskSchedulerError(err))
}
return nil
}
// Stop kills and releases a running task.
// https://docs.microsoft.com/en-us/windows/desktop/api/taskschd/nf-taskschd-irunningtask-stop
func (r *RunningTask) Stop() error {
_, err := oleutil.CallMethod(r.taskObj, "Stop")
if err != nil {
return fmt.Errorf("error stopping running task %s: %v", r.Path, getTaskSchedulerError(err))
}
r.Release()
return nil
}
// Release frees the running task COM object. Must be called before
// program termination to avoid memory leaks.
func (r *RunningTask) Release() {
if !r.isReleased && r.taskObj != nil {
r.taskObj.Release()
r.isReleased = true
}
}
// Run starts an instance of a registered task. If the task was started successfully,
// a pointer to a running task will be returned.
// https://docs.microsoft.com/en-us/windows/desktop/api/taskschd/nf-taskschd-iregisteredtask-run
func (r *RegisteredTask) Run(args ...string) (RunningTask, error) {
return r.RunEx(args, TASK_RUN_NO_FLAGS, 0, "")
}
// RunEx starts an instance of a registered task. If the task was started successfully,
// a pointer to a running task will be returned.
// https://docs.microsoft.com/en-us/windows/desktop/api/taskschd/nf-taskschd-iregisteredtask-runex
func (r *RegisteredTask) RunEx(args []string, flags TaskRunFlags, sessionID int, user string) (RunningTask, error) {
if !r.Enabled {
return RunningTask{}, fmt.Errorf("error running registered task %s: cannot run a disabled task", r.Path)
}
runningTaskObj, err := oleutil.CallMethod(r.taskObj, "RunEx", args, int(flags), sessionID, user)
if err != nil {
return RunningTask{}, fmt.Errorf("error running registered task %s: %v", r.Path, getTaskSchedulerError(err))
}
return parseRunningTask(runningTaskObj.ToIDispatch())
}
// GetInstances returns all of the currently running instances of a registered task.
// https://docs.microsoft.com/en-us/windows/desktop/api/taskschd/nf-taskschd-iregisteredtask-getinstances
func (r *RegisteredTask) GetInstances() (RunningTaskCollection, error) {
runningTasks, err := oleutil.CallMethod(r.taskObj, "GetInstances", 0)
if err != nil {
return nil, fmt.Errorf("error getting instances of registered task %s: %v", r.Path, getTaskSchedulerError(err))
}
runningTasksObj := runningTasks.ToIDispatch()
defer runningTasksObj.Release()
var parsedRunningTasks RunningTaskCollection
err = oleutil.ForEach(runningTasksObj, func(v *ole.VARIANT) error {
runningTaskObj := v.ToIDispatch()
parsedRunningTask, err := parseRunningTask(runningTaskObj)
if err != nil {
if errors.Is(err, ErrRunningTaskCompleted) {
return nil
}
return fmt.Errorf("error parsing running task: %v", err)
}
parsedRunningTasks = append(parsedRunningTasks, parsedRunningTask)
return nil
})
if err != nil {
return nil, err
}
return parsedRunningTasks, nil
}
// Stop kills all running instances of the registered task that the current
// user has access to. If all instances were killed, Stop returns true,
// otherwise Stop returns false.
// https://docs.microsoft.com/en-us/windows/desktop/api/taskschd/nf-taskschd-iregisteredtask-stop
func (r *RegisteredTask) Stop() error {
_, err := oleutil.CallMethod(r.taskObj, "Stop", 0)
if err != nil {
return fmt.Errorf("error stopping registered task %s: %v", r.Path, getTaskSchedulerError(err))
}
return nil
}
// Release frees the registered task COM object. Must be called before
// program termination to avoid memory leaks.
func (r *RegisteredTask) Release() {
if !r.isReleased && r.taskObj != nil {
r.taskObj.Release()
r.isReleased = true
}
}
// RunningTaskCollection is a collection of running tasks.
type RunningTaskCollection []RunningTask
// Stop kills and frees all the running tasks COM objects in the
// collection. If an error is encountered while stopping a running
// task, Stop returns the error without attempting to stop any
// other running tasks in the collection.
func (r RunningTaskCollection) Stop() error {
for _, runningTask := range r {
if err := runningTask.Stop(); err != nil {
return err
}
}
return nil
}
// Release frees all the running task COM objects in the collection.
// Must be called before program termination to avoid memory leaks.
func (r RunningTaskCollection) Release() {
for _, runningTask := range r {
runningTask.Release()
}
}
// RegisteredTaskCollection is a collection of registered tasks.
type RegisteredTaskCollection []RegisteredTask
// Release frees all the registered task COM objects in the collection.
// Must be called before program termination to avoid memory leaks.
func (r RegisteredTaskCollection) Release() {
for _, registeredTask := range r {
registeredTask.Release()
}
}
// Release frees all the registered task COM objects in the folder and
// all subfolders. Must be called before program termination to avoid
// memory leaks.
func (f *TaskFolder) Release() {
if !f.isReleased {
f.RegisteredTasks.Release()
for _, subFolder := range f.SubFolders {
subFolder.RegisteredTasks.Release()
}
f.isReleased = true
}
}