R
Addressed the issue of the addition of the task in the Task Scheduler, which periodically checks the status of service and starts it if it has not yet been launched.I guess I could use some of that. net start servicenamebut it's a little longer.@ECHO OFF
SET ServiceName=%~1
SC QUERYEX "%ServiceName%" | FIND "STATE" | FIND /v "RUNNING" > NUL && (
ECHO %ServiceName% is not running
ECHO START %ServiceName%
NET START "%ServiceName%" > NUL || (
ECHO "%ServiceName%" wont start
EXIT /B 1
)
ECHO "%ServiceName%" is started
EXIT /B 0
) || (
ECHO "%ServiceName%" is running
EXIT /B 0
)
https://library.octopusdeploy.com/step-templates/17bc51d1-8b88-4aad-b188-24a0904d0bf2/actiontemplate-windows-scheduled-task-create : $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)
{
# 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)) )
{
switch -Regex ($Schedule)
{
"MINUTE|HOURLY|ONLOGON|ONIDLE" {
$argumentList += @( "/MO", $Interval );
}
"WEEKLY|MONTHLY" {
$argumentList += @( "/RI", $Interval );
}
"ONCE|ONSTART|ONEVENT" {
# we don't currently support providing an XPATH query string
throw new-object System.NotImplementedException("Unsupported schedule option '$Schedule'.");
}
}
}
if( -not (StringIsNullOrWhiteSpace($Days)) -And $Schedule -Ne "DAILY" )
{
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 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']
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
Write-Output "Successfully Created $taskName"
Enable-ScheduledTask($taskName)
Write-Output "$taskName enabled"
}
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" )
{
$ParamsForRunning = @{
TaskName = 'Service WatchDog'
RunAsUser= 'System'
Command = $OctopusParameters["Octopus.Action[Deploy Worker].Output.Package.InstallationDirectoryPath"]+"\check-service.cmd"
Arguments = 'SomeWorkerServiceName'
Schedule = 'MINUTE'
Interval = 20
}
Invoke-OctopusStep -OctopusParameters $ParamsForRunning;
}
Not through Octopus, specific things can be replaced by a direct call.Because of inconvenience, when the service is wilfully stopped, it has to change the Startup Type to the disabled to avoid launch.