-
-
Save sarathms/b5bf3dbaee58080086ffa7a7045dec8b to your computer and use it in GitHub Desktop.
SCHEDULES PROBE-CLI AT T+2 MINUTES
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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') | |
}) | |
}) | |
}, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Empty |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.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