1 #!powershell
2
3 # Copyright: (c) 2017, Ansible Project
4 # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5
6 #Requires -Module Ansible.ModuleUtils.CamelConversion
7 #Requires -Module Ansible.ModuleUtils.Legacy
8 #Requires -Module Ansible.ModuleUtils.SID
9
10 $params = Parse-Args -arguments $args
11 $_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
12
13 $path = Get-AnsibleParam -obj $params -name "path" -type "str" -default "\"
14 $name = Get-AnsibleParam -obj $params -name "name" -type "str"
15
16 $result = @{
17 changed = $false
18 }
19
20 $task_enums = @"
21 public enum TASK_ACTION_TYPE
22 {
23 TASK_ACTION_EXEC = 0,
24 // The below are not supported and are only kept for documentation purposes
25 TASK_ACTION_COM_HANDLER = 5,
26 TASK_ACTION_SEND_EMAIL = 6,
27 TASK_ACTION_SHOW_MESSAGE = 7
28 }
29
30 public enum TASK_LOGON_TYPE
31 {
32 TASK_LOGON_NONE = 0,
33 TASK_LOGON_PASSWORD = 1,
34 TASK_LOGON_S4U = 2,
35 TASK_LOGON_INTERACTIVE_TOKEN = 3,
36 TASK_LOGON_GROUP = 4,
37 TASK_LOGON_SERVICE_ACCOUNT = 5,
38 TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD = 6
39 }
40
41 public enum TASK_RUN_LEVEL
42 {
43 TASK_RUNLEVEL_LUA = 0,
44 TASK_RUNLEVEL_HIGHEST = 1
45 }
46
47 public enum TASK_STATE
48 {
49 TASK_STATE_UNKNOWN = 0,
50 TASK_STATE_DISABLED = 1,
51 TASK_STATE_QUEUED = 2,
52 TASK_STATE_READY = 3,
53 TASK_STATE_RUNNING = 4
54 }
55
56 public enum TASK_TRIGGER_TYPE2
57 {
58 TASK_TRIGGER_EVENT = 0,
59 TASK_TRIGGER_TIME = 1,
60 TASK_TRIGGER_DAILY = 2,
61 TASK_TRIGGER_WEEKLY = 3,
62 TASK_TRIGGER_MONTHLY = 4,
63 TASK_TRIGGER_MONTHLYDOW = 5,
64 TASK_TRIGGER_IDLE = 6,
65 TASK_TRIGGER_REGISTRATION = 7,
66 TASK_TRIGGER_BOOT = 8,
67 TASK_TRIGGER_LOGON = 9,
68 TASK_TRIGGER_SESSION_STATE_CHANGE = 11
69 }
70 "@
71
72 $original_tmp = $env:TMP
73 $env:TMP = $_remote_tmp
74 Add-Type -TypeDefinition $task_enums
75 $env:TMP = $original_tmp
76
Get-PropertyValue($task_property, $com, $property)77 Function Get-PropertyValue($task_property, $com, $property) {
78 $raw_value = $com.$property
79
80 if ($null -eq $raw_value) {
81 return $null
82 } elseif ($raw_value.GetType().Name -eq "__ComObject") {
83 $com_values = @{}
84 Get-Member -InputObject $raw_value -MemberType Property | ForEach-Object {
85 $com_value = Get-PropertyValue -task_property $property -com $raw_value -property $_.Name
86 $com_values.$($_.Name) = $com_value
87 }
88
89 return ,$com_values
90 }
91
92 switch ($property) {
93 DaysOfWeek {
94 $value_list = @()
95 $map = @(
96 @{ day = "sunday"; bitwise = 0x01 }
97 @{ day = "monday"; bitwise = 0x02 }
98 @{ day = "tuesday"; bitwise = 0x04 }
99 @{ day = "wednesday"; bitwise = 0x08 }
100 @{ day = "thursday"; bitwise = 0x10 }
101 @{ day = "friday"; bitwise = 0x20 }
102 @{ day = "saturday"; bitwise = 0x40 }
103 )
104 foreach ($entry in $map) {
105 $day = $entry.day
106 $bitwise = $entry.bitwise
107 if ($raw_value -band $bitwise) {
108 $value_list += $day
109 }
110 }
111
112 $value = $value_list -join ","
113 break
114 }
115 DaysOfMonth {
116 $value_list = @()
117 $map = @(
118 @{ day = "1"; bitwise = 0x01 }
119 @{ day = "2"; bitwise = 0x02 }
120 @{ day = "3"; bitwise = 0x04 }
121 @{ day = "4"; bitwise = 0x08 }
122 @{ day = "5"; bitwise = 0x10 }
123 @{ day = "6"; bitwise = 0x20 }
124 @{ day = "7"; bitwise = 0x40 }
125 @{ day = "8"; bitwise = 0x80 }
126 @{ day = "9"; bitwise = 0x100 }
127 @{ day = "10"; bitwise = 0x200 }
128 @{ day = "11"; bitwise = 0x400 }
129 @{ day = "12"; bitwise = 0x800 }
130 @{ day = "13"; bitwise = 0x1000 }
131 @{ day = "14"; bitwise = 0x2000 }
132 @{ day = "15"; bitwise = 0x4000 }
133 @{ day = "16"; bitwise = 0x8000 }
134 @{ day = "17"; bitwise = 0x10000 }
135 @{ day = "18"; bitwise = 0x20000 }
136 @{ day = "19"; bitwise = 0x40000 }
137 @{ day = "20"; bitwise = 0x80000 }
138 @{ day = "21"; bitwise = 0x100000 }
139 @{ day = "22"; bitwise = 0x200000 }
140 @{ day = "23"; bitwise = 0x400000 }
141 @{ day = "24"; bitwise = 0x800000 }
142 @{ day = "25"; bitwise = 0x1000000 }
143 @{ day = "26"; bitwise = 0x2000000 }
144 @{ day = "27"; bitwise = 0x4000000 }
145 @{ day = "28"; bitwise = 0x8000000 }
146 @{ day = "29"; bitwise = 0x10000000 }
147 @{ day = "30"; bitwise = 0x20000000 }
148 @{ day = "31"; bitwise = 0x40000000 }
149 )
150
151 foreach ($entry in $map) {
152 $day = $entry.day
153 $bitwise = $entry.bitwise
154 if ($raw_value -band $bitwise) {
155 $value_list += $day
156 }
157 }
158
159 $value = $value_list -join ","
160 break
161 }
162 WeeksOfMonth {
163 $value_list = @()
164 $map = @(
165 @{ week = "1"; bitwise = 0x01 }
166 @{ week = "2"; bitwise = 0x02 }
167 @{ week = "3"; bitwise = 0x04 }
168 @{ week = "4"; bitwise = 0x04 }
169 )
170
171 foreach ($entry in $map) {
172 $week = $entry.week
173 $bitwise = $entry.bitwise
174 if ($raw_value -band $bitwise) {
175 $value_list += $week
176 }
177 }
178
179 $value = $value_list -join ","
180 break
181 }
182 MonthsOfYear {
183 $value_list = @()
184 $map = @(
185 @{ month = "january"; bitwise = 0x01 }
186 @{ month = "february"; bitwise = 0x02 }
187 @{ month = "march"; bitwise = 0x04 }
188 @{ month = "april"; bitwise = 0x08 }
189 @{ month = "may"; bitwise = 0x10 }
190 @{ month = "june"; bitwise = 0x20 }
191 @{ month = "july"; bitwise = 0x40 }
192 @{ month = "august"; bitwise = 0x80 }
193 @{ month = "september"; bitwise = 0x100 }
194 @{ month = "october"; bitwise = 0x200 }
195 @{ month = "november"; bitwise = 0x400 }
196 @{ month = "december"; bitwise = 0x800 }
197 )
198
199 foreach ($entry in $map) {
200 $month = $entry.month
201 $bitwise = $entry.bitwise
202 if ($raw_value -band $bitwise) {
203 $value_list += $month
204 }
205 }
206
207 $value = $value_list -join ","
208 break
209 }
210 Type {
211 if ($task_property -eq "actions") {
212 $value = [Enum]::ToObject([TASK_ACTION_TYPE], $raw_value).ToString()
213 } elseif ($task_property -eq "triggers") {
214 $value = [Enum]::ToObject([TASK_TRIGGER_TYPE2], $raw_value).ToString()
215 }
216 break
217 }
218 RunLevel {
219 $value = [Enum]::ToObject([TASK_RUN_LEVEL], $raw_value).ToString()
220 break
221 }
222 LogonType {
223 $value = [Enum]::ToObject([TASK_LOGON_TYPE], $raw_value).ToString()
224 break
225 }
226 UserId {
227 $sid = Convert-ToSID -account_name $raw_value
228 $value = Convert-FromSid -sid $sid
229 }
230 GroupId {
231 $sid = Convert-ToSID -account_name $raw_value
232 $value = Convert-FromSid -sid $sid
233 }
234 default {
235 $value = $raw_value
236 break
237 }
238 }
239
240 return ,$value
241 }
242
243 $service = New-Object -ComObject Schedule.Service
244 try {
245 $service.Connect()
246 } catch {
247 Fail-Json -obj $result -message "failed to connect to the task scheduler service: $($_.Exception.Message)"
248 }
249
250 try {
251 $task_folder = $service.GetFolder($path)
252 $result.folder_exists = $true
253 } catch {
254 $result.folder_exists = $false
255 if ($null -ne $name) {
256 $result.task_exists = $false
257 }
258 Exit-Json -obj $result
259 }
260
261 $folder_tasks = $task_folder.GetTasks(1)
262 $folder_task_names = @()
263 $folder_task_count = 0
264 $task = $null
265 for ($i = 1; $i -le $folder_tasks.Count; $i++) {
266 $task_name = $folder_tasks.Item($i).Name
267 $folder_task_names += $task_name
268 $folder_task_count += 1
269
270 if ($null -ne $name -and $task_name -eq $name) {
271 $task = $folder_tasks.Item($i)
272 }
273 }
274 $result.folder_task_names = $folder_task_names
275 $result.folder_task_count = $folder_task_count
276
277 if ($null -ne $name) {
278 if ($null -ne $task) {
279 $result.task_exists = $true
280
281 # task state
282 $result.state = @{
283 last_run_time = (Get-Date $task.LastRunTime -Format s)
284 last_task_result = $task.LastTaskResult
285 next_run_time = (Get-Date $task.NextRunTime -Format s)
286 number_of_missed_runs = $task.NumberOfMissedRuns
287 status = [Enum]::ToObject([TASK_STATE], $task.State).ToString()
288 }
289
290 # task definition
291 $task_definition = $task.Definition
292 $ignored_properties = @("XmlText")
293 $properties = @("principal", "registration_info", "settings")
294 $collection_properties = @("actions", "triggers")
295
296 foreach ($property in $properties) {
297 $property_name = $property -replace "_"
298 $result.$property = @{}
299 $values = $task_definition.$property_name
300 Get-Member -InputObject $values -MemberType Property | ForEach-Object {
301 if ($_.Name -notin $ignored_properties) {
302 $result.$property.$($_.Name) = (Get-PropertyValue -task_property $property -com $values -property $_.Name)
303 }
304 }
305 }
306
307 foreach ($property in $collection_properties) {
308 $result.$property = @()
309 $collection = $task_definition.$property
310 $collection_count = $collection.Count
311 for ($i = 1; $i -le $collection_count; $i++) {
312 $item = $collection.Item($i)
313 $item_info = @{}
314
315 Get-Member -InputObject $item -MemberType Property | ForEach-Object {
316 if ($_.Name -notin $ignored_properties) {
317 $item_info.$($_.Name) = (Get-PropertyValue -task_property $property -com $item -property $_.Name)
318 }
319 }
320 $result.$property += $item_info
321 }
322 }
323 } else {
324 $result.task_exists = $false
325 }
326 }
327
328 $result = Convert-DictToSnakeCase -dict $result
329
330 Exit-Json -obj $result
331