71 lines
2.5 KiB
Go
71 lines
2.5 KiB
Go
package startup
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/xml"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
const watchdogArg = "-ensure"
|
||
|
|
|
||
|
|
// watchdogTaskXML builds a Task Scheduler 2.0 XML action with Command and
|
||
|
|
// Arguments as separate fields. Paths must not be wrapped in extra quotes —
|
||
|
|
// schtasks /TR quoting is what made the watchdog flash and exit.
|
||
|
|
func watchdogTaskXML(exe string) string {
|
||
|
|
exe = strings.Trim(exe, `"`)
|
||
|
|
var b strings.Builder
|
||
|
|
b.WriteString(`<?xml version="1.0" encoding="UTF-16"?>`)
|
||
|
|
b.WriteByte('\n')
|
||
|
|
b.WriteString(`<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">`)
|
||
|
|
b.WriteString(`<RegistrationInfo><Description>win64_mp watchdog</Description></RegistrationInfo>`)
|
||
|
|
b.WriteString(`<Triggers><TimeTrigger>`)
|
||
|
|
b.WriteString(`<Repetition><Interval>PT5M</Interval><StopAtDurationEnd>false</StopAtDurationEnd></Repetition>`)
|
||
|
|
b.WriteString(`<StartBoundary>2000-01-01T00:00:00</StartBoundary>`)
|
||
|
|
b.WriteString(`<Enabled>true</Enabled>`)
|
||
|
|
b.WriteString(`</TimeTrigger></Triggers>`)
|
||
|
|
b.WriteString(`<Principals><Principal id="Author">`)
|
||
|
|
b.WriteString(`<LogonType>InteractiveToken</LogonType>`)
|
||
|
|
b.WriteString(`<RunLevel>LeastPrivilege</RunLevel>`)
|
||
|
|
b.WriteString(`</Principal></Principals>`)
|
||
|
|
b.WriteString(`<Settings>`)
|
||
|
|
b.WriteString(`<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>`)
|
||
|
|
b.WriteString(`<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>`)
|
||
|
|
b.WriteString(`<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>`)
|
||
|
|
b.WriteString(`<Hidden>true</Hidden>`)
|
||
|
|
b.WriteString(`<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>`)
|
||
|
|
b.WriteString(`<AllowStartOnDemand>true</AllowStartOnDemand>`)
|
||
|
|
b.WriteString(`<Enabled>true</Enabled>`)
|
||
|
|
b.WriteString(`<StartWhenAvailable>true</StartWhenAvailable>`)
|
||
|
|
b.WriteString(`<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>`)
|
||
|
|
b.WriteString(`<Priority>7</Priority>`)
|
||
|
|
b.WriteString(`</Settings>`)
|
||
|
|
b.WriteString(`<Actions Context="Author"><Exec>`)
|
||
|
|
b.WriteString(`<Command>`)
|
||
|
|
b.WriteString(xmlEscape(exe))
|
||
|
|
b.WriteString(`</Command>`)
|
||
|
|
b.WriteString(`<Arguments>`)
|
||
|
|
b.WriteString(watchdogArg)
|
||
|
|
b.WriteString(`</Arguments>`)
|
||
|
|
if dir := winDir(exe); dir != "" {
|
||
|
|
b.WriteString(`<WorkingDirectory>`)
|
||
|
|
b.WriteString(xmlEscape(dir))
|
||
|
|
b.WriteString(`</WorkingDirectory>`)
|
||
|
|
}
|
||
|
|
b.WriteString(`</Exec></Actions></Task>`)
|
||
|
|
return b.String()
|
||
|
|
}
|
||
|
|
|
||
|
|
func xmlEscape(s string) string {
|
||
|
|
var b strings.Builder
|
||
|
|
_ = xml.EscapeText(&b, []byte(s))
|
||
|
|
return b.String()
|
||
|
|
}
|
||
|
|
|
||
|
|
func winDir(p string) string {
|
||
|
|
p = strings.TrimRight(p, `/\`)
|
||
|
|
i := strings.LastIndexAny(p, `/\`)
|
||
|
|
if i <= 0 {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
return p[:i]
|
||
|
|
}
|