Created
May 15, 2022 21:39
-
-
Save karlgluck/69dc30f95cc892b9e5c41c2753a735b8 to your computer and use it in GitHub Desktop.
Example of a scheduled job
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This will register a new job that removes itself from Get-ScheduledJob when finished | |
$Trigger = New-JobTrigger -Once -At (Get-Date).AddSeconds(3) | |
$TaskName = "SelfDestructingJob" | |
Register-ScheduledJob -Trigger $Trigger -Name $TaskName ` | |
-ScriptBlock ([scriptblock]::Create(@" | |
("Started job at " + (Get-Date) + ", waiting...") | Out-File -FilePath 'C:\ProofThatItWorks.txt' | |
Start-Sleep 3 | |
("Finished at " + (Get-Date)) | Out-File -Append -FilePath 'C:\ProofThatItWorks.txt' | |
Unregister-ScheduledJob -Name '$TaskName' -Force | |
"@)) | |
# Wait for the job to finish | |
# https://docs.microsoft.com/en-us/windows/win32/taskschd/task-scheduler-error-and-success-constants?redirectedfrom=MSDN | |
Set-Variable -Name "SCHED_S_TASK_HAS_NOT_RUN" -Value 0x00041303 -Option Constant | |
Set-Variable -Name "SCHED_S_TASK_RUNNING" -Value 0x00041301 -Option Constant | |
Set-Variable -Name "SCHED_S_TASK_SUCCESS" -Value 0x0 -Option Constant | |
do { | |
Start-Sleep 1 | |
$Task = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue | |
if ($null -ne $Task) | |
{ | |
$ResultCode = ($Task | Get-ScheduledTaskInfo).LastTaskResult | |
switch ($ResultCode) | |
{ | |
$SCHED_S_TASK_HAS_NOT_RUN { Write-Host "Waiting to run the task" } | |
$SCHED_S_TASK_RUNNING { Write-Host "Task is running!" } | |
$SCHED_S_TASK_SUCCESS { Write-Host "Task completed" } | |
default { Write-Host "Error! $ResultCode" } | |
} | |
} | |
else | |
{ | |
Write-Host "Task was removed" | |
$ResultCode = -1 | |
} | |
} while (@($SCHED_S_TASK_HAS_NOT_RUN, $SCHED_S_TASK_RUNNING) -contains $ResultCode) | |
<# | |
# This seems to be a more correct alternative to simply calling | |
# Unregister-ScheduledJob within the job itself, but it results | |
# in the SelfDestructingJob task being "corrupted" and removed on the next run. | |
# The above does this sometimes too, but since this is more involved, prefer the other version | |
# https://iamsupergeek.com/self-deleting-scheduled-task-via-powershell/ | |
$TaskName = "SelfDestructingJob" | |
$Trigger = New-JobTrigger -Once -At (get-date).AddSeconds(5) | |
$JobOptions = New-ScheduledJobOption -StartIfOnBattery -RunElevated | |
$SelfDestructingJob = Register-ScheduledJob -Name $TaskName -Trigger $Trigger -ScheduledJobOption $JobOptions ` | |
-ScriptBlock { | |
"Started job, waiting for 10 seconds..." | Out-File -FilePath 'C:\ProofThatItWorks.txt' | |
Sleep 10 | |
"Finished!" | Out-File -Append -FilePath 'C:\ProofThatItWorks.txt' | |
} | |
$SelfDestructingTask = Get-ScheduledTask -TaskName $TaskName | |
# https://iamsupergeek.com/self-deleting-scheduled-task-via-powershell/ | |
#$SelfDestructingTask.Triggers[0].StartBoundary = [DateTime]::Now.ToString("yyyy-MM-dd'T'HH:mm:ss") | |
$SelfDestructingTask.Triggers[0].EndBoundary = [DateTime]::Now.AddSeconds(5).ToString("yyyy-MM-dd'T'HH:mm:ss") | |
$SelfDestructingTask.Settings.AllowHardTerminate = $True | |
$SelfDestructingTask.Settings.DeleteExpiredTaskAfter = 'PT0S' | |
$SelfDestructingTask.Settings.ExecutionTimeLimit = 'PT1H' | |
$SelfDestructingTask.Settings.volatile = $False | |
# Save tweaks to the Scheduled Task | |
$SelfDestructingTask | Set-ScheduledTask | |
# From https://docs.microsoft.com/en-us/windows/win32/taskschd/task-scheduler-error-and-success-constants?redirectedfrom=MSDN | |
Set-Variable -Name "SCHED_S_TASK_HAS_NOT_RUN" -Value 0x00041303 -Option Constant | |
Set-Variable -Name "SCHED_S_TASK_RUNNING" -Value 0x00041301 -Option Constant | |
Set-Variable -Name "SCHED_S_TASK_SUCCESS" -Value 0x0 -Option Constant | |
do { | |
Sleep 1 | |
$Task = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue | |
if ($null -ne $Task) | |
{ | |
$ResultCode = ($Task | Get-ScheduledTaskInfo).LastTaskResult | |
switch ($ResultCode) | |
{ | |
$SCHED_S_TASK_HAS_NOT_RUN { Write-Host "Waiting to run the task" } | |
$SCHED_S_TASK_RUNNING { Write-Host "Task is running!" } | |
$SCHED_S_TASK_SUCCESS { Write-Host "Task completed" } | |
default { Write-Host "Error! $ResultCode" } | |
} | |
} | |
else | |
{ | |
Write-Host "Task was removed" | |
$ResultCode = -1 | |
} | |
} while (@($SCHED_S_TASK_HAS_NOT_RUN, $SCHED_S_TASK_RUNNING) -contains $ResultCode) | |
<# | |
# This is an attempt to use Start-Job (which actually *has* an event that fires when it ends) | |
# However, a ScheduledJob will not terminate until all its sub-Jobs are finished. | |
$Trigger = New-JobTrigger -Once -At (get-date).AddSeconds(5) | |
$JobOptions = New-ScheduledJobOption -StartIfOnBattery -RunElevated | |
$SelfDestructingJob = Register-ScheduledJob -Name "SelfDestructingJob" -Trigger $Trigger -ScheduledJobOption $JobOptions ` | |
-ScriptBlock { | |
Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "ScriptBlock Start" | |
# In order to clean up, a non-scheduled Job waits for the scheduled job | |
# This is because non-scheduled jobs fire an event when the end we can use to | |
# remove that job when it's finished. | |
$JobToUnregisterSelfDestructingJob = Start-Job { | |
$JobToUnregister = Get-ScheduledJob -Name "SelfDestructingJob" | |
Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "Monitoring..." | |
do { | |
[console]::beep(400,150) | |
Sleep 1 | |
$ResultCode = (Get-ScheduledTask -TaskName "SelfDestructingJob.txt" | Get-ScheduledTaskInfo).LastTaskResult | |
switch ($ResultCode) | |
{ | |
$SCHED_S_TASK_HAS_NOT_RUN { Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "Waiting to run the task" } | |
$SCHED_S_TASK_RUNNING { Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "Task is running!" } | |
$SCHED_S_TASK_SUCCESS { Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "Task completed" } | |
default { Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "Error! $ResultCode" } | |
} | |
} while ($ResultCode -ne $SCHED_S_TASK_SUCCESS) | |
Sleep 1 | |
Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "Done!" | |
[console]::beep(523,250) | |
Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "Unregistered $JobToUnregister" | |
Unregister-ScheduledJob $JobToUnregister | |
} | |
Register-ObjectEvent -InputObject $JobToUnregisterSelfDestructingJob -EventName StateChanged -Action { | |
[console]::beep(659,250) | |
Unregister-Event $EventSubscriber.SourceIdentifier | |
Remove-Job $EventSubscriber.SourceIdentifier | |
Remove-Job -Id $EventSubscriber.SourceObject.Id | |
Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "Cleaned up the unregister job" | |
} | |
Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "=== Started Job Work ===" | |
# Do some stuff that takes a while to complete | |
Sleep 5 | |
Out-File -Append -FilePath "C:\SelfDestructingJob.txt" -InputObject "=== Finished Job Work ===" | |
} | |
Write-Host "Monitoring..." | |
do { | |
[console]::beep(400,150) | |
Sleep 1 | |
$ResultCode = (Get-ScheduledTask -TaskName "SelfDestructingJob" | Get-ScheduledTaskInfo).LastTaskResult | |
switch ($ResultCode) | |
{ | |
$SCHED_S_TASK_HAS_NOT_RUN { Write-Host "Waiting to run the task" } | |
$SCHED_S_TASK_RUNNING { Write-Host "Task is running!" } | |
$SCHED_S_TASK_SUCCESS { Write-Host "Task completed" } | |
default { Write-Host "Error! $ResultCode" } | |
} | |
} while ($ResultCode -ne $SCHED_S_TASK_SUCCESS) | |
Write-Host "Finished with the script" | |
#> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment