Skip to content

Commit 1ef739a

Browse files
v1.2
moved to external help code cleanup Added Get-ScheduledJobResult command and associated class Added auto completer for Name parameter in Export-ScheduledJob and Get-ScheduledJobResult increased required PowerShell version to 5.0
1 parent ac26fc3 commit 1ef739a

File tree

8 files changed

+1479
-380
lines changed

8 files changed

+1479
-380
lines changed

ScheduledJobFunctions.ps1

Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
Function Export-ScheduledJob {
2+
3+
[cmdletbinding(SupportsShouldProcess, DefaultParameterSetName = "name")]
4+
5+
Param(
6+
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = "name")]
7+
[ValidateNotNullorEmpty()]
8+
[string]$Name,
9+
10+
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = "job")]
11+
[ValidateNotNullorEmpty()]
12+
[alias("job")]
13+
[Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition]$ScheduledJob,
14+
15+
[ValidateScript( {
16+
if (-Not (Test-Path -path $_)) {
17+
Throw "Could not verify the path."
18+
}
19+
else {
20+
$True
21+
}
22+
})]
23+
[ValidateScript( {Test-Path $_})]
24+
[string]$Path = (Get-Location).Path,
25+
[switch]$Passthru
26+
)
27+
28+
Begin {
29+
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN] Starting $($myinvocation.mycommand)"
30+
} #begin
31+
32+
Process {
33+
34+
if ($Name) {
35+
Write-verbose "[$((Get-Date).TimeofDay) PROCESS] Getting scheduled job $job"
36+
Try {
37+
$ExportJob = Get-ScheduledJob -Name $name -ErrorAction Stop
38+
}
39+
Catch {
40+
Write-Warning "Failed to get scheduled job $name"
41+
#bail out
42+
Return
43+
}
44+
} #if
45+
else {
46+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Using scheduled job $($scheduledjob.name)"
47+
$ExportJob = $scheduledjob
48+
}
49+
50+
$ExportPath = Join-path -Path $path -ChildPath "$($ExportJob.Name).xml"
51+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Starting the export process of $($ExportJob.Name) to $ExportPath"
52+
53+
$ExportJob | Select-Object -property Name,
54+
@{Name = "Scriptblock";
55+
Expression = {
56+
($_.InvocationInfo.Parameters.Item(0) |
57+
Where-Object {$_.name -eq "ScriptBlock"}).value
58+
}
59+
},
60+
@{Name = "FilePath";
61+
Expression = {
62+
($_.InvocationInfo.Parameters.Item(0)|
63+
Where-Object {$_.name -eq "FilePath"}).value
64+
}
65+
},
66+
@{Name = "ArgumentList";
67+
Expression = {
68+
($_.InvocationInfo.Parameters.Item(0) |
69+
Where-Object {$_.name -eq "ArgumentList"}).value
70+
}
71+
},
72+
@{Name = "Authentication";
73+
Expression = {
74+
($_.InvocationInfo.Parameters.Item(0) |
75+
Where-Object {$_.name -eq "Authentication"}).value
76+
}
77+
},
78+
@{Name = "InitializationScript";
79+
Expression = {
80+
($_.InvocationInfo.Parameters.Item(0) |
81+
Where-Object {$_.name -eq "InitializationScript"}).value
82+
}
83+
},
84+
@{Name = "RunAs32";
85+
Expression = {
86+
($_.InvocationInfo.Parameters.Item(0) |
87+
Where-Object {$_.name -eq "RunAs32"}).value
88+
}
89+
},
90+
@{Name = "Credential";
91+
Expression = {
92+
$_.Credential.UserName
93+
}
94+
},
95+
@{Name = "Options";
96+
Expression = {
97+
#don't export the job definition here
98+
$_.Options | Select-Object -property * -ExcludeProperty JobDefinition
99+
}
100+
},
101+
@{Name = "JobTriggers";
102+
Expression = {
103+
#don't export the job definition here
104+
$_.JobTriggers | Select-Object -property * -ExcludeProperty JobDefinition
105+
}
106+
}, ExecutionHistoryLength, Enabled |
107+
Export-Clixml -Path $ExportPath
108+
109+
if ($Passthru) {
110+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Writing the export file item to the pipeline"
111+
Get-Item -Path $ExportPath
112+
}
113+
114+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Export finished."
115+
} #process
116+
117+
End {
118+
Write-Verbose "[$((Get-Date).TimeofDay) END] Ending $($myinvocation.MyCommand)"
119+
} #end
120+
} #end Export-ScheduledJob
121+
122+
123+
Function Import-ScheduledJob {
124+
125+
[cmdletbinding(SupportsShouldProcess)]
126+
127+
Param(
128+
[Parameter(Position = 0, Mandatory, ValueFromPipeline)]
129+
[alias("name", "pspath")]
130+
[ValidateScript( {
131+
if (-Not (Test-Path -path $_)) {
132+
Throw "Could not verify the path."
133+
}
134+
else {
135+
$True
136+
}
137+
})]
138+
[string]$Path,
139+
[switch]$Passthru
140+
)
141+
142+
Begin {
143+
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN] Starting $($myinvocation.mycommand)"
144+
} #begin
145+
146+
Process {
147+
148+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] processing $path"
149+
150+
#define a hashtable of values for Register-ScheduledJob
151+
$paramHash = @{
152+
ErrorAction = "Stop"
153+
}
154+
155+
$Imported = Import-Clixml -path $Path
156+
157+
#$cmd = "Register-ScheduledJob -name ""$($Imported.Name)"""
158+
$paramHash.Add("Name", $Imported.Name)
159+
160+
if ($Imported.scriptblock) {
161+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Found a scriptblock"
162+
163+
$paramHash.Add("ScriptBlock", [scriptblock]::Create($Imported.Scriptblock))
164+
165+
}
166+
elseif ($Imported.FilePath) {
167+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Found a filepath"
168+
#$cmd+= " -FilePath $($Imported.FilePath)"
169+
$paramHash.Add("FilePath", $Imported.Filepath)
170+
}
171+
else {
172+
#this should never really happen
173+
Write-Warning "Failed to find a scriptblock or file path"
174+
#bail out
175+
Return
176+
}
177+
178+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing additional job elements"
179+
if ($Imported.ArgumentList) {
180+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..ArgumentList"
181+
182+
$paramHash.Add("ArgumentList", $ImportFile.ArgumentList)
183+
}
184+
185+
if ($Imported.Authentication) {
186+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..Authentication"
187+
188+
$paramhash.Add("Authentication", $Imported.Authentication)
189+
}
190+
191+
if ($Imported.Credential) {
192+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..Credential"
193+
194+
$paramHash.Add("credential", $Imported.Credential)
195+
}
196+
197+
if ($Imported.InitializationScript) {
198+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..InitializationScript"
199+
200+
$paramHash.Add("InitializationScript", [scriptblock]::Create($Imported.InitializationScript))
201+
202+
}
203+
204+
if ($Imported.ExecutionHistoryLength) {
205+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..ExecutionHistoryLength"
206+
207+
$paramHash.Add("MaxResultCount", $Imported.ExecutionHistoryLength)
208+
}
209+
210+
if ($Imported.RunAs32) {
211+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..RunAs32"
212+
213+
$paramHash.Add("RunAs32", $True)
214+
}
215+
216+
if ($Imported.Options) {
217+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing Options"
218+
219+
$optionHash = @{
220+
RunElevated = $Imported.Options.RunElevated
221+
HideInTaskScheduler = -Not ($Imported.Options.ShowInTaskScheduler)
222+
RestartOnIdleResume = $Imported.Options.RestartOnIdleResume
223+
MultipleInstancePolicy = $Imported.Options.MultipleInstancePolicy
224+
DoNotAllowDemandStart = $Imported.Options.DoNotAllowDemandStart
225+
RequireNetwork = -Not ($Imported.Options.RunWithoutNetwork)
226+
StopIfGoingOffIdle = $Imported.Options.StopIfGoingOffIdle
227+
WakeToRun = $Imported.Options.WakeToRun
228+
ContinueIfGoingOnBattery = -Not ($Imported.Options.StopIfGoingOnBatteries)
229+
StartIfOnBattery = $Imported.Options.StartIfOnBatteries
230+
IdleTimeout = $Imported.Options.IdleTimeout
231+
IdleDuration = $Imported.Options.IdleDuration
232+
StartIfIdle = -Not ($Imported.Options.StartIfNotIdle)
233+
}
234+
235+
$jobOption = New-ScheduledJobOption @optionHash
236+
237+
$paramhash.Add("ScheduledJobOption", $jobOption)
238+
}
239+
240+
if ($Imported.JobTriggers) {
241+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing Job Triggers"
242+
243+
#define an array to hold triggers
244+
$Triggers = @()
245+
246+
#enumerate each job trigger
247+
foreach ($trigger in $Imported.JobTriggers) {
248+
#test for parameter set
249+
Switch ($trigger.Frequency.Value) {
250+
"Once" {
251+
$TriggerCmd = "New-JobTrigger -Once -At ""$($trigger.At)"""
252+
if ($trigger.RepetitionDuration) {
253+
$TriggerCmd += " -RepetitionDuration $($trigger.RepetitionDuration)"
254+
}
255+
if ($trigger.RepetitionInterval) {
256+
$TriggerCmd += "-RepetitionInterval $($trigger.RepetitionInterval)"
257+
}
258+
} #once
259+
"Weekly" {
260+
$TriggerCmd = "New-JobTrigger -Weekly -DaysOfWeek $($trigger.DaysOfWeek) -WeeksInterval $($trigger.Interval) -At ""$($trigger.At)"""
261+
} #weekly
262+
"Daily" {
263+
$TriggerCmd = "New-JobTrigger -Daily -DaysInterval $($trigger.Interval) -At ""$($trigger.At)"""
264+
} #Daily
265+
"AtLogon" {
266+
$TriggerCmd = "New-JobTrigger -AtLogOn -User $($trigger.user)"
267+
} #AtLogon
268+
"AtStartup" {
269+
$TriggerCmd = "New-JobTrigger -AtStartup"
270+
} #AtStartup
271+
Default {
272+
#no frequency
273+
Write-Warning "No trigger found"
274+
} #Default
275+
} #end switch
276+
277+
#define a new trigger and add to the array
278+
$TriggerCmd += " -randomdelay $($trigger.RandomDelay)"
279+
Write-Verbose $triggerCmd
280+
$Triggers += Invoke-Expression -Command $TriggerCmd
281+
} #foreach trigger
282+
283+
284+
$paramHash.Add("Trigger", $Triggers)
285+
}
286+
287+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Creating the scheduled job"
288+
Write-Verbose ($paramhash | Out-String)
289+
#create the scheduled job
290+
if ($PSCmdlet.ShouldProcess($imported.Name)) {
291+
$newJob = Register-ScheduledJob @paramhash
292+
293+
#if the job is disabled, then
294+
if (-Not ($Imported.Enabled)) {
295+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Disabling the job"
296+
$newJob | Disable-ScheduledJob
297+
}
298+
if ($Passthru) {
299+
Get-ScheduledJob $imported.Name
300+
}
301+
} #should process
302+
} #process
303+
304+
End {
305+
Write-Verbose "[$((Get-Date).TimeofDay) END] Ending $($myinvocation.MyCommand)"
306+
} #end
307+
} #close Import-ScheduledJob
308+
309+
310+
Function Get-ScheduledJobResult {
311+
312+
[cmdletbinding()]
313+
Param(
314+
[Parameter(Position = 0)]
315+
[ValidateNotNullorEmpty()]
316+
[string]$Name = "*",
317+
[validatescript( {$_ -gt 0})]
318+
[int]$Newest = 1,
319+
[switch]$All
320+
)
321+
322+
Begin {
323+
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN] Starting $($myinvocation.mycommand)"
324+
} #begin
325+
326+
Process {
327+
#only show results for Enabled jobs
328+
Try {
329+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting scheduled jobs for $name"
330+
$jobs = Get-ScheduledJob -Name $name -ErrorAction Stop -ErrorVariable ev
331+
}
332+
Catch {
333+
Write-Warning $ev.errorRecord.Exception
334+
}
335+
336+
if ($jobs) {
337+
#filter unless asking for all jobs
338+
339+
if ($All) {
340+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting all jobs"
341+
}
342+
else {
343+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting enabled jobs only"
344+
$jobs = $jobs | where-object Enabled
345+
}
346+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing $($jobs.count) found jobs"
347+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting newest $newest job results"
348+
349+
$data = $jobs | foreach-object {
350+
#get job and select all properties to create a custom object
351+
Try {
352+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Trying to get jobs for $($_.name)"
353+
Get-Job -Name $_.name -Newest $Newest -ErrorAction stop | foreach-object {
354+
[scheduledjobresult]::new($_)
355+
}
356+
357+
} #Try
358+
Catch {
359+
Write-Warning "Scheduled job $($_.TargetObject) has not been run yet."
360+
}
361+
} #Foreach Scheduled Job
362+
363+
#write a sorted result to the pipeline
364+
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Here are your $($data.count) results"
365+
$data | Sort-Object -Property PSEndTime -Descending
366+
367+
} #if $jobs
368+
} #process
369+
End {
370+
Write-Verbose "[$((Get-Date).TimeofDay) END] Ending $($myinvocation.MyCommand)"
371+
} #end
372+
373+
} #end function
374+

0 commit comments

Comments
 (0)