functions/ScheduledTasks.ps1

function Stop-BeamScheduledTask {
    param($taskPath, $taskName,$timeoutSec = 10, [switch][bool] $disable) 

    $timeout = $timeoutSec
    ipmo require
    req scheduledtasks

    $tn = $taskName
    $folder = $taskPath

    $folder = "\" + $folder.Trim("\","/") + "\" 

    write-host "looking for task '$($tn)' in folder '$folder'"
    try {
        $t = scheduledtasks\get-Scheduledtask -taskname $tn -taskpath $folder  -ErrorAction SilentlyContinue 
    } catch {
        # for some reason, get-scheduledtask throws if $folder is not found, even if erroraction is SilentlyContinue
    }
    
    if ($t -ne $null) {
        if ($disable) {
            write-host "$(get-date) disabling task '$folder$($t.Taskname)'"
            $t | scheduledtasks\disable-scheduledtask    
        }
        write-host "$(get-date) stopping task '$folder$($t.Taskname)'"
        $t | scheduledtasks\stop-scheduledtask
        $c = 0
        do {
            $c++
            Start-Sleep -Seconds 1
            $t = scheduledtasks\get-Scheduledtask -taskname $tn -taskpath $folder          
            write-host "$tn : $($t.State)"
        } while ($t.State -ne "Ready" -and $t.State -ne "Disabled" -and $c -lt $timeout) 



        $t | format-table | out-string | write-host
        if ($t.State -eq "Disabled") {
            write-warning "task '$fulltn' is Disabled!"
        }
        elseif ($t.State -ne "Ready") {
            throw "task '$fulltn' failed to stop. status = '$($t.State)' after $timeout s"
        }

        try {
        $processPath = ($t.Definition.Actions | select -first 1).Path
        if ($processpath -eq $null) {
            Write-Warning "failed to retrieve executable path from dask definition"
        }
        else {
            $processName = [System.IO.Path]::GetFileNameWithoutExtension($processPAth)
            Write-Verbose "looking for process path $processpath name $processname" -Verbose
            $hangingprocs = $true
            for($retries = 10; $hangingprocs -and $retries -gt 0; $retries--) {
                $procs = @(get-process $processName | ? { $_.Path -eq $processPath })
                if ($procs.Count -gt 0) {
                    write-warning "there are still processes running with task executable '$processPath'"
                foreach ($p in $procs) {
                        write-warning "killing process $($p.Id) (as user '$env:USERDOMAIN\$env:USERNAME')"
                        try {
                            $p.Kill()
                        } catch {
                            write-warning "failed to kill process $($p.Id): $($_.Message)"
                            if ($retries - 1 -eq 0) {
                                throw
                            }
                            #throw
                        }
                    }
                    Start-Sleep 1
            }
            else {
                    $hangingprocs = $false
                }
            } 
        }
        } catch {
            write-warning "failed to kill hanging '$tn' process: $($_.message)"
            write-warning "$($_.scriptstacktrace)"
            throw
        }

    }
}

function Start-BeamScheduledTask {
    param($taskPath, $taskName, $timeoutSec = 10) 

    $timeout = $timeoutSec
    ipmo require
    req scheduledtasks

    $folder = $taskPath
    $folder = "\" + $folder.Trim("\","/") + "\" 
    $tn = $taskName
    $fulltn = "$taskpath$taskname"

    write-host "$(get-date) starting task '$fulltn'" 
    $t = scheduledtasks\get-Scheduledtask -taskname $tn -taskpath $folder           

    if ($t -eq $null) { throw "task $tn not found in folder $folder" }
    # create-taskhere returns wrong task type (from taskscheduler module instead of scheduledtasks ?)
    # the task may have been disabled
    if (!$t.settings.enabled) {
        $t | scheduledtasks\Enable-ScheduledTask -ErrorAction stop
    }
    $t | scheduledtasks\Start-ScheduledTask -erroraction stop

    $c = 0
    do {
        $c++
        Start-Sleep -Seconds 1
        $t = scheduledtasks\get-Scheduledtask -taskname $tn -taskpath $folder           
        write-host "$tn : $($t.State)"
    } while ($t.State -ne "Running" -and $t.State -ne "Disabled" -and $c -lt $timeout) 

    $t | format-table | out-string | write-host
    if ($t.State -eq "Disabled") {
        write-warning "task '$fulltn' is Disabled! Assuming this is intentional, will not treat this as error."
    }
    elseif ($t.State -ne "Running") {
        throw "task '$fulltn' failed to start. status = '$($t.State)' after $timeout s"
    }
}

function Restart-BeamScheduledTask {
    param($taskPath, $taskName) 

    Stop-BeamScheduledTask -taskpath $taskpath -taskname $taskname
    Start-BeamScheduledTask -taskpath $taskpath -taskname $taskname
}

new-alias Restart-ScheduledTask Restart-BeamScheduledTask -force