Create and Run a windows scheduled task

hi All,
i am trying to create and run instantly a scheduled task from octopus to my server
code i used is

$ErrorActionPreference = “Stop”;
Set-StrictMode -Version “Latest”;

use http://msdn.microsoft.com/en-us/library/windows/desktop/bb736357(v=vs.85).aspx for API reference

Function Create-ScheduledTask($TaskName,$RunAsUser,$RunAsPassword,$TaskRun,$Arguments,$Schedule,$StartTime,$StartDate,$RunWithElevatedPermissions,$Days,$Interval,$Duration, $Modifier)
{

# SCHTASKS /Create [/S system [/U username [/P [password]]]]
#     [/RU username [/RP password]] /SC schedule [/MO modifier] [/D day]
#     [/M months] [/I idletime] /TN taskname /TR taskrun [/ST starttime]
#     [/RI interval] [ {/ET endtime | /DU duration} [/K] [/XML xmlfile] [/V1]]
#     [/SD startdate] [/ED enddate] [/IT | /NP] [/Z] [/F] [/HRESULT] [/?]

# note - /RL and /DELAY appear in the "Parameter list" for "SCHTASKS /Create /?" but not in the syntax above

$argumentList = @();
$argumentList += @( "/Create" );

$argumentList += @( "/RU", "`"$RunAsUser`"" );

if( -not (StringIsNullOrWhiteSpace($RunAsPassword)))
{
    $argumentList += @( "/RP", $RunAsPassword );
}

$argumentList += @( "/SC", $Schedule );

if( -not (StringIsNullOrWhiteSpace($Interval)) )
{
    $argumentList += @( "/RI", $Interval );
}

if( -not (StringIsNullOrWhiteSpace($Modifier)))
{
    switch -Regex ($Schedule)
    {
        "MINUTE|HOURLY|DAILY|WEEKLY|MONTHLY|ONEVENT" {
            $argumentList += @( "/MO", $Modifier );
        }
        "ONCE|ONSTART|ONLOGON|ONIDLE" {
            $argumentList += @( "/MO" );
    }
}
}

if( -not (StringIsNullOrWhiteSpace($Days)))
{
    if($Schedule -ne "WEEKDAYS") {
        $argumentList += @( "/D", $Days );
    } else {
        $argumentList += @( "/D", "MON,TUE,WED,THU,FRI" );
    }
}

$argumentList += @( "/TN", "`"$TaskName`"" );

if( $Arguments )
{
    $argumentList += @( "/TR", "`"'$TaskRun' $Arguments`"" );
}
else
{
    $argumentList += @( "/TR", "`"'$TaskRun'`"" );
}

if( -not (StringIsNullOrWhiteSpace($StartTime)) )
{
    $argumentList += @( "/ST", $StartTime );
}

if( -not (StringIsNullOrWhiteSpace($Duration)) )
{
    $argumentList += @( "/DU", $Duration );
}

if( -not (StringIsNullOrWhiteSpace($StartDate)) )
{
    $argumentList += @( "/SD", $StartDate );
}

$argumentList += @( "/F" );

if( $RunWithElevatedPermissions )
{
    $argumentList += @( "/RL", "HIGHEST" );
}

Invoke-CommandLine -FilePath     "$($env:SystemRoot)\System32\schtasks.exe" `
                   -ArgumentList $argumentList;

}

Function Delete-ScheduledTask($TaskName) {
# SCHTASKS /Delete [/S system [/U username [/P [password]]]]
# /TN taskname [/F] [/HRESULT] [/?]
Invoke-CommandLine -FilePath “$($env:SystemRoot)\System32\schtasks.exe” -ArgumentList @( "/Delete", "/S", "localhost", "/TN", "“$TaskName`”", “/F” );
}

Function Stop-ScheduledTask($TaskName) {
# SCHTASKS /End [/S system [/U username [/P [password]]]]
# /TN taskname [/HRESULT] [/?]
Invoke-CommandLine -FilePath “$($env:SystemRoot)\System32\schtasks.exe” -ArgumentList @( "/End", "/S", "localhost", "/TN", "“$TaskName`”" );
}

Function Start-ScheduledTask($TaskName) {
# SCHTASKS /Run [/S system [/U username [/P [password]]]] [/I]
# /TN taskname [/HRESULT] [/?]
Invoke-CommandLine -FilePath “$($env:SystemRoot)\System32\schtasks.exe” -ArgumentList @( "/Run", "/S", "localhost", "/TN", "“$TaskName`”" );
}

Function Enable-ScheduledTask($TaskName) {
# SCHTASKS /Change [/S system [/U username [/P [password]]]] /TN taskname
# { [/RU runasuser] [/RP runaspassword] [/TR taskrun] [/ST starttime]
# [/RI interval] [ {/ET endtime | /DU duration} [/K] ]
# [/SD startdate] [/ED enddate] [/ENABLE | /DISABLE] [/IT] [/Z] }
# [/HRESULT] [/?]
Invoke-CommandLine -FilePath “$($env:SystemRoot)\System32\schtasks.exe” -ArgumentList @( "/Change", "/S", "localhost", "/TN", "“$TaskName`”", “/ENABLE” );
}

Function Disable-ScheduledTask($TaskName) {
# SCHTASKS /Change [/S system [/U username [/P [password]]]] /TN taskname
# { [/RU runasuser] [/RP runaspassword] [/TR taskrun] [/ST starttime]
# [/RI interval] [ {/ET endtime | /DU duration} [/K] ]
# [/SD startdate] [/ED enddate] [/ENABLE | /DISABLE] [/IT] [/Z] }
# [/HRESULT] [/?]
Invoke-CommandLine -FilePath “$($env:SystemRoot)\System32\schtasks.exe” -ArgumentList @( "/Change", "/S", "localhost", "/TN", "“$TaskName`”", “/DISABLE” );
}

Function ScheduledTask-Exists($taskName) {
$schedule = new-object -com Schedule.Service
$schedule.connect()
$tasks = $schedule.getfolder("").gettasks(0)
foreach ($task in ($tasks | select Name)) {
#echo “TASK: $($task.name)”
if($task.Name -eq $taskName) {
#write-output “$task already exists”
return $true
}
}
return $false
}

Function StringIsNullOrWhitespace([string] $string)
{
if ($string -ne $null) { $string = $string.Trim() }
return [string]::IsNullOrEmpty($string)
}

function Invoke-CommandLine
{
param
(
[Parameter(Mandatory=$true)]
[string] $FilePath,
[Parameter(Mandatory=$false)]
[string[]] $ArgumentList = @( ),
[Parameter(Mandatory=$false)]
[string[]] $SuccessCodes = @( 0 )
)
write-host ($FilePath + " " + ($ArgumentList -join " "));
$process = Start-Process -FilePath $FilePath -ArgumentList $ArgumentList -Wait -NoNewWindow -PassThru;
if( $SuccessCodes -notcontains $process.ExitCode )
{
throw new-object System.InvalidOperationException(“process terminated with exit code ‘$($process.ExitCode)’.”);
}
}

function Invoke-OctopusStep
{
param
(
[Parameter(Mandatory=$true)]
[hashtable] $OctopusParameters
)

$taskName = $OctopusParameters['TaskName']
$runAsUser = $OctopusParameters['RunAsUser']
$runAsPassword = $OctopusParameters['RunAsPassword']
$command = $OctopusParameters['Command']
$arguments = $OctopusParameters['Arguments']
$schedule = $OctopusParameters['Schedule']
$startTime = $OctopusParameters['StartTime']
$startDate = $OctopusParameters['StartDate']

if( $OctopusParameters.ContainsKey("RunWithElevatedPermissions") )
{
    $runWithElevatedPermissions = [boolean]::Parse($OctopusParameters['RunWithElevatedPermissions'])
}
else
{
    $runWithElevatedPermissions = $false;
}

$days = $OctopusParameters['Days']
$interval = $OctopusParameters['Interval']
$duration = $OctopusParameters['Duration']
$Modifier = $OctopusParameters['Modifier']

if((ScheduledTask-Exists($taskName))){
    Write-Output "$taskName already exists, Tearing down..."
    Write-Output "Stopping $taskName..."
    Stop-ScheduledTask($taskName)
    Write-Output "Successfully Stopped $taskName"
    Write-Output "Deleting $taskName..."
    Delete-ScheduledTask($taskName)
    Write-Output "Successfully Deleted $taskName"
}
Write-Output "Creating Scheduled Task - $taskName"

Create-ScheduledTask $taskName $runAsUser $runAsPassword $command $arguments $schedule $startTime $startDate $runWithElevatedPermissions $days $interval $duration $Modifier
Write-Output "Successfully Created $taskName"

if( $OctopusParameters.ContainsKey('TaskStatus') )
{
    $taskStatus = $OctopusParameters['TaskStatus']
    if( -not (StringIsNullOrWhiteSpace($taskStatus)) )
    {
        if ( $taskStatus -eq "ENABLE" )
        {
            Enable-ScheduledTask($taskName)
            Write-Output "$taskName enabled"
        }
        elseif ( $taskStatus -eq "DISABLE" )
        {
            Disable-ScheduledTask($taskName)
            Write-Output "$taskName disabled"
        }
        else
        {
            Write-Output "$taskName status unchanged (on create, will be enabled)"
        }
    }
}

if( $OctopusParameters.ContainsKey("StartNewTaskNow") )
{
    $startNewTaskNow = [boolean]::Parse($OctopusParameters['StartNewTaskNow'])
}
else
{
    $startNewTaskNow = $false;
}

if( $startNewTaskNow ) {
  Start-ScheduledTask($taskName)
}

}

only execute the step if it’s called from octopus deploy,

and skip it if we’re runnning inside a Pester test

if( Test-Path -Path “Variable:OctopusParameters” )
{
Invoke-OctopusStep -OctopusParameters $OctopusParameters;
}

Hi @paggarwal5154,

Thanks for getting in touch with us.

For scheduled tasks, we have a Step template you can use to set this up and you can see it on https://library.octopus.com/step-templates/17bc51d1-8b88-4aad-b188-24a0904d0bf2/actiontemplate-windows-scheduled-task-create.

Another approach would be to use Octopus Runbooks with a Scheduled Runbook Trigger and have it execute from Octopus. The benefit here is that you can see when the task ran without having to log on to the server and it’s in a centralized location.

Please let me know if I can help further.

Thanks,

Derek

Hi Derek,
thanks for responding but i think the step template you mentioned here is the same i used to create and run my scheduled task.
the second approach of Octopus Runbooks option is not showing up in my octopus.
My octopus version Octopus 3.17.14

Hi @paggarwal5154,

Thanks for coming back to me.

Runbooks was introduced in Octopus 2020.1, so you’d need to upgrade from version 3.17.14 to a newer version of Octopus to get Runbooks support. You can see the release notes on https://octopus.com/downloads/compare?from=3.17.14&to=2020.4.2 for that upgrade.

You can see how to upgrade Octopus on https://octopus.com/docs/administration/upgrading/guide.

This step on https://library.octopus.com/step-templates/17bc51d1-8b88-4aad-b188-24a0904d0bf2/actiontemplate-windows-scheduled-task-create will only create the step, to run the scheduled task, you will need to use Powershell to execute the Scheduled task.

To execute the task, you can run Start-ScheduledTask -TaskName "ScanSoftware" and you can see more about this command on https://docs.microsoft.com/en-us/powershell/module/scheduledtasks/start-scheduledtask?view=win10-ps

Please let me know if I can help further.

Thanks

Derek