Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karlgluck/69dc30f95cc892b9e5c41c2753a735b8 to your computer and use it in GitHub Desktop.
Save karlgluck/69dc30f95cc892b9e5c41c2753a735b8 to your computer and use it in GitHub Desktop.
Example of a scheduled job
# 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