Skip to content

Instantly share code, notes, and snippets.

@sarathms
Created December 16, 2020 22:38
Show Gist options
  • Save sarathms/b5bf3dbaee58080086ffa7a7045dec8b to your computer and use it in GitHub Desktop.
Save sarathms/b5bf3dbaee58080086ffa7a7045dec8b to your computer and use it in GitHub Desktop.
SCHEDULES PROBE-CLI AT T+2 MINUTES
<!DOCTYPE html>
<html lang="en">
<head>
<title>Task Scheduler POC</title>
<link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
<h2>Schedule OONI Probe Desktop on Windows</h2>
<h3> Scheduled Task </h3>
<div id='info'></div>
<br /><br />
<button id='schedule'> Schedule </button>
<button id='delete'> Delete </button>
<button id='scheduler'> Open Scheduler UI </button>
<div class='error'>
</div>
<script>
require('./renderer.js')
</script>
</body>
</html>
// The ipcMain and ipcRenderer modules allow communication between the mai
// process and the renderer processes.
//
// For more info, see:
// https://electronjs.org/docs/api/ipc-main
// https://electronjs.org/docs/api/ipc-renderer
const { app, BrowserWindow, ipcMain } = require('electron')
const fs = require('fs')
// const task = require('windows-scheduler')
const batchFilePath = './ooniprobe-schedule.bat'
const batchFileContents = `
@echo off
set OONI_HOME=C:\\Users\\deept\\AppData\\Roaming\\OONI\ Probe\\ooni_home
cmd /C ${process.env.LOCALAPPDATA}\\Programs\\ooniprobe-desktop\\resources\\bin\\ooniprobe.exe run im > ${process.env.TMP}\\log.txt
`
console.dir(process.env)
const pad2 = (n) => ('00'+n).slice(-2)
app.whenReady().then(() => {
const mainWindow = new BrowserWindow({
height: 600,
width: 600,
webPreferences: {
nodeIntegration: true
}
})
ipcMain.on('open-scheduler', () => {
const schedulerPath = 'C:\\Windows\\System32\\taskschd.msc'
const process = require('child_process')
var child = process.spawn('cmd', ['/c', schedulerPath])
})
ipcMain.on('schedule-task', async (event) => {
const now = new Date()
const tplus1 = `${pad2(now.getHours())}:${pad2(now.getMinutes() + 1)}`
fs.writeFileSync(batchFilePath, batchFileContents)
const taskToRun = `${batchFilePath}`
try {
const result = await task.create('TestTask',
taskToRun,
{ frequency: 'DAILY', starttime: tplus1 }
)
mainWindow.webContents.send('task-scheduled', result)
} catch (e) {
console.dir(e)
mainWindow.webContents.send('error', 'create-failed', e)
}
})
ipcMain.on('get-task', async (event, arg) => {
try {
const t = await task.get('TestTask', 'LIST', true)
event.returnValue = t.split('\n')
} catch (e) {
event.returnValue = e
mainWindow.webContents.send('error', 'get-failed', e)
}
})
ipcMain.on('delete-task', async (event) => {
try {
await task.delete('TestTask')
mainWindow.webContents.send('task-deleted')
} catch (e) {
mainWindow.webContents.send('error', 'delete-failed', e)
}
})
mainWindow.loadFile('index.html')
})
// -------------------------------------------------------------
const {execFileSync} = require('child_process')
function exec(command) {
return execFileSync('cmd', [`/C schtasks ${command}`])
}
const task = {
get: function (taskname, format, verbose){
return new Promise( function(resolve, reject){
let command = ` /Query`
if (taskname) command = command.concat(` /TN ${taskname}`)
if (format) command = command.concat(` /FO ${format}`)
if (verbose) command = command.concat(` /V`)
try {
// pipe stderr to null to suppress unmanageable error message when not found
const result = exec(command.concat(' 2> nul'))
resolve(result.toString())
} catch (err) {
reject('Task: Get error')
}
})
},
create: function(taskname, taskrun, schedule) {
return new Promise( (resolve, reject) => {
// snipped validate
this.get(taskname)
.then( () => {
return reject('Task: Create error - Taskname already exists')
})
.catch( () => {
let command = ` /Create /TN ${taskname} /TR ${taskrun}`
if (schedule.frequency) command = command.concat(` /SC ${schedule.frequency}`)
if (schedule.modifier) command = command.concat(` /MO ${schedule.modifier}`)
if (schedule.day) command = command.concat(` /D ${schedule.day}`)
if (schedule.month) command = command.concat(` /M ${schedule.month}`)
if (schedule.starttime) command = command.concat(` /ST ${schedule.starttime}`)
if (schedule.endtime) command = command.concat(` /ET ${schedule.endtime}`)
if (schedule.every) command = command.concat(` /RI ${schedule.every}`)
if (schedule.startdate) command = command.concat(` /SD ${schedule.startdate}`)
if (schedule.enddate) command = command.concat(` /ED ${schedule.enddate}`)
try {
console.log(`Final command: ${command}`)
const result = exec(command)
resolve(result.toString())
} catch (err) {
reject('Task: Create error')
}
})
})
},
update: function (taskname, taskrun, schedule, enable){
return new Promise( (resolve, reject) => {
// try {
// validate.update_params(taskname, taskrun, schedule, enable)
// } catch (err) {
// return reject(err.message)
// }
this.get(taskname)
.then( () => {
let command = ` /Change /TN ${taskname}`
if (taskrun) command = command.concat(` /TR ${taskrun}`)
if (schedule) {
if (schedule.starttime) command = command.concat(` /ST ${schedule.starttime}`)
if (schedule.endtime) command = command.concat(` /ET ${schedule.endtime}`)
if (schedule.every) command = command.concat(` /RI ${schedule.every}`)
if (schedule.startdate) command = command.concat(` /SD ${schedule.startdate}`)
if (schedule.enddate) command = command.concat(` /ED ${schedule.enddate}`)
}
if (enable && enable==true) command = command.concat(` /ENABLE`)
if (enable && enable==false) command = command.concat(` /DISABLE`)
try {
const result = exec(command)
return resolve(result.toString())
} catch (err) {
return reject('Task: Update error')
}
})
.catch( (err) => {
return reject('Task: Update error - Taskname not found')
})
})
},
delete: function (taskname){
return new Promise( (resolve, reject) => {
// try {
// validate.taskname(taskname)
// } catch (err) {
// return reject(err.message)
// }
this.get(taskname)
.then( () => {
try {
const result = exec(` /Delete /TN ${taskname} /F`)
resolve(result.toString())
} catch (err) {
reject('Task: Delete error')
}
})
.catch( () => {
return reject('Task: Delete error - Taskname not found')
})
})
},
run: function (taskname){
return new Promise( (resolve, reject) => {
// try {
// validate.taskname(taskname)
// } catch (err) {
// return reject(err.message)
// }
this.get(taskname)
.then( () => {
try {
const result = exec(` /Run /TN ${taskname}`)
resolve(result.toString())
} catch (err) {
resolve('Task: Run error')
}
})
.catch( () => {
return reject('Task: Run error - Taskname not found')
})
})
},
end: function (taskname){
return new Promise( (resolve, reject) => {
// try {
// validate.taskname(taskname)
// } catch (err) {
// return reject(err.message)
// }
this.get(taskname)
.then( () => {
try {
const result = exec(` /End /TN ${taskname}`)
resolve(result.toString())
} catch (err) {
resolve('Task: End error')
}
})
.catch( () => {
return reject('Task: End error - Taskname not found')
})
})
},
}
const { ipcRenderer, shell } = require('electron')
document.querySelector('#schedule').addEventListener('click', () => {
ipcRenderer.send('schedule-task')
})
document.querySelector('#delete').addEventListener('click', () => {
ipcRenderer.send('delete-task')
})
document.querySelector('#scheduler').addEventListener('click', () => {
ipcRenderer.send('open-scheduler')
})
ipcRenderer.on('task-scheduled', (_, ...args) => {
clearError()
showInfo(`Task scheduled: ${args}`)
})
ipcRenderer.on('task-deleted', (_, ...args) => {
clearError()
showInfo(`Task deleted: ${args}`)
})
const existingTask = ipcRenderer.sendSync('get-task')
// document.querySelector('#info').innerHTML = `<ul>${existingTask.map(entry => `<li>${entry}</li>`).join('')}</ul>`
document.querySelector('#info').innerHTML = `<ul>${JSON.stringify(existingTask, null, 2)}</ul>`
ipcRenderer.on('error', (event, args) => {
document.querySelector('.error').innerHTML = JSON.stringify(args, null, 2)
})
const showInfo = (info) => document.querySelector('#info').innerHTML = info
const clearError = () => document.querySelector('.error').innerHTML = null
.error {
display: block;
margin: 16px 0px;
padding: 16px;
color: lightcoral;
border: 1px solid gray;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment