1

I need two scheduled tasks to be created with powershell that will run a powershell script each.

One should trigger at 08:00 every day and run every two hours. So at 10:00 ,12:00, 14:00 etc.. The other at 9 every day and run every two hours. So at 11:00 ,13:00, 15:00 etc..

If the user is not logged, the tasks should still be triggered as soon as he logs in. Lets say he logs in 9:35 this will trigger both tasks. How can they not run simultaneously?

I tried to add delay to one of them but there is a chance the delay will be 0

A solution can be:

  1. When they run simultaneously they check if this is the case somehow and one of the exits. Or,
  2. Some other method of ensuring they dont intercept
   $taskAction1 = New-ScheduledTaskAction -Execute 'Powershell.exe' -argument "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File $script1"
   $taskAction2 = New-ScheduledTaskAction -Execute 'Powershell.exe' -argument "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File $script2"

   $taskSettings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -Hidden -DontStopIfGoingOnBatteries

   $taskTrigger = New-ScheduledTaskTrigger -AtLogOn
   $taskTriggerWithDelay = New-ScheduledTaskTrigger -AtLogOn -RandomDelay 00:15:00

   Register-ScheduledTask -User System -Action $taskAction1 -Trigger $TasKTrigger -TaskName "Task1" -RunLevel Highest -Settings $TaskSettings -f | Out-Null
   Register-ScheduledTask -User System -Action $taskAction2 -Trigger $taskTriggerWithDelay -TaskName "Task2" -RunLevel Highest -Settings $TaskSettings -f | Out-Null

   $trigger= Get-ScheduledTask -TaskName Task1
   $trigger.Triggers.repetition.Interval = "PT2H"
   $trigger.Triggers.repetition.duration = ""
   $trigger | Set-ScheduledTask | Out-Null

   $trigger= Get-ScheduledTask -TaskName Task2
   $trigger.Triggers.repetition.Interval = "PT2H"
   $trigger.Triggers.repetition.duration = ""
   $trigger | Set-ScheduledTask | Out-Null

  • 2
    Sounds like homework. ;-) What did you try so far? Show your code please. You might have a look at [the tour](https://stackoverflow.com/tour) or maybe [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask). – Olaf Jan 31 '19 at 09:49
  • I added my code. Well its not homework, rather a part of a bigger project. – Dimitrios Arampatzis Jan 31 '19 at 11:47

1 Answers1

2

The problem is about mutual exclusion, a well-researched problem.

A simple solution is based on a shared resource. When task starts, it tries to acquire an exclusive lock on the resource. If this is not possible, the task waits and tries again until a timeout or lock is granted. When lock holding task has finished its work, it will release the lock as part of cleanup.

The simple solution doesn't guarantee fair scheduling, so look up more implementations if fairness is needed.

As for the comment: don't rely on pid. In Windows, process ids can be reused.

For a quick demo, let's use a flag file like so,

function getlock() {
    $file = $null
    while($file -eq $null) {
        try { $file = [System.IO.File]::Open("c:\temp\flag.txt", "open", "read", "none") } catch {
            write-host "waiting..."
            start-sleep -seconds 2
        }
    }

    write-host "got lock!"
    start-sleep -seconds 5
    $file.close()
}

Try it out by loading the function into two Powershell sessions and calling them within a few seconds. Increase the 5 second sleep if you are having problems with task switching. Each function will try to get an exclusive lock to a flag file. Should that be impossible, an exception will be thrown. The process that's late in the game will sleep for two seconds and try again until the first one releases the lock. See File.Open() for more details about file share modes.

Flag files have issues, so for more robust IPC, look at earlier an answer. It's for C#, but can be tweaked for Powershell too.

vonPryz
  • 22,996
  • 7
  • 54
  • 65
  • Can this lock be associated with the pid of the scheduled task? Meaning that if the scheduled task ends / fails or if the pc gets shutdown during the process will the file be unlocked? Could you specify the powershell cmdlet that does this? – Dimitrios Arampatzis Jan 31 '19 at 12:55