node-windows
Advanced tools
Comparing version 1.0.0-beta.7 to 1.0.0-beta.8
var path = require('path'), | ||
bin = path.join(__dirname,'..','bin'), | ||
exec = require('child_process').exec; | ||
bin = path.join(__dirname, '..', 'bin'), | ||
exec = require('child_process').exec; | ||
var params = function(options,callback) { | ||
callback = callback || function(){}; | ||
var params = function (options, callback) { | ||
callback = callback || function () { }; | ||
options = options || {}; | ||
if (typeof options === 'function'){ | ||
if (typeof options === 'function') { | ||
callback = options; | ||
options = {}; | ||
} | ||
if (typeof options !== 'object'){ | ||
if (typeof options !== 'object') { | ||
throw 'Invalid options parameter.'; | ||
} | ||
return {options:options,callback:callback}; | ||
return { options: options, callback: callback }; | ||
} | ||
@@ -42,5 +42,5 @@ | ||
*/ | ||
elevate: function(cmd,options,callback) { | ||
var p = params(options,callback); | ||
exec('"'+path.join(bin,'elevate','elevate.cmd')+'" '+cmd,p.options,p.callback); | ||
elevate: function (cmd, options, callback) { | ||
var p = params(options, callback); | ||
exec('"' + path.join(bin, 'elevate', 'elevate.cmd') + '" ' + cmd, p.options, p.callback); | ||
}, | ||
@@ -69,5 +69,5 @@ | ||
*/ | ||
sudo: function(cmd,password,options,callback){ | ||
sudo: function (cmd, password, options, callback) { | ||
password = password || ''; | ||
if (typeof password !== 'string'){ | ||
if (typeof password !== 'string') { | ||
callback = options; | ||
@@ -77,5 +77,5 @@ options = password; | ||
} | ||
var p = params(options,callback); | ||
exec(path.join(bin,'sudowin','sudo.exe')+' '+(password !== '' ? '-p '+password:'')+cmd,p.options,p.callback); | ||
var p = params(options, callback); | ||
exec(path.join(bin, 'sudowin', 'sudo.exe') + ' ' + (password !== '' ? '-p ' + password : '') + cmd, p.options, p.callback); | ||
} | ||
} | ||
} |
var exec = require('child_process').exec, | ||
bin = require('./binaries'); | ||
bin = require('./binaries'); | ||
@@ -16,6 +16,6 @@ module.exports = { | ||
*/ | ||
isAdminUser: function(callback){ | ||
exec('NET SESSION',function(err,so,se){ | ||
if (se.length !== 0){ | ||
bin.elevate('NET SESSION',function(_err,_so,_se){ | ||
isAdminUser: function (callback) { | ||
exec('NET SESSION', function (err, so, se) { | ||
if (se.length !== 0) { | ||
bin.elevate('NET SESSION', function (_err, _so, _se) { | ||
callback(_se.length === 0); | ||
@@ -39,17 +39,17 @@ }); | ||
*/ | ||
kill: function(pid,force,callback){ | ||
if (!pid){ | ||
kill: function (pid, force, callback) { | ||
if (!pid) { | ||
throw new Error('PID is required for the kill operation.'); | ||
} | ||
if (isNaN(pid)) { | ||
if (typeof isNaN(pid)) { | ||
throw new Error('PID must be a number.') | ||
} | ||
callback = callback || function(){}; | ||
if (typeof force == 'function'){ | ||
callback = callback || function () { }; | ||
if (typeof force == 'function') { | ||
callback = force; | ||
force = false; | ||
} | ||
exec("taskkill /PID "+pid+(force==true?' /f':''),callback); | ||
exec("taskkill /PID " + pid + (force == true ? ' /f' : ''), callback); | ||
}, | ||
@@ -65,20 +65,20 @@ | ||
*/ | ||
list: function(callback,verbose){ | ||
list: function (callback, verbose) { | ||
verbose = typeof verbose == 'boolean' ? verbose : false; | ||
exec('tasklist /FO CSV'+(verbose==true?' /V':''),function(err,stdout,stderr){ | ||
exec('tasklist /FO CSV' + (verbose == true ? ' /V' : ''), function (err, stdout, stderr) { | ||
var p = stdout.split('\r\n'); | ||
var proc = []; | ||
var head = null; | ||
while (p.length > 1){ | ||
while (p.length > 1) { | ||
var rec = p.shift(); | ||
rec = rec.replace(/\"\,/gi,'";').replace(/\"|\'/gi,'').split(';'); | ||
if (head == null){ | ||
rec = rec.replace(/\"\,/gi, '";').replace(/\"|\'/gi, '').split(';'); | ||
if (head == null) { | ||
head = rec; | ||
for (var i=0;i<head.length;i++){ | ||
head[i] = head[i].replace(/ /gi,''); | ||
for (var i = 0; i < head.length; i++) { | ||
head[i] = head[i].replace(/ /gi, ''); | ||
} | ||
} else { | ||
var tmp = {}; | ||
for (var i=0;i<rec.length;i++){ | ||
tmp[head[i]] = rec[i].replace(/\"|\'/gi,''); | ||
for (var i = 0; i < rec.length; i++) { | ||
tmp[head[i]] = rec[i].replace(/\"|\'/gi, ''); | ||
} | ||
@@ -92,2 +92,2 @@ proc.push(tmp); | ||
}; | ||
}; |
@@ -33,9 +33,9 @@ /** | ||
var exec = require('child_process').exec, | ||
path = require('path'), | ||
fs = require('fs'), | ||
PermError = 'Permission Denied. Requires administrative privileges.', | ||
wincmd = require('./binaries'), | ||
Logger = require('./eventlog'), | ||
daemonDir = 'daemon', | ||
wrapper = path.resolve(path.join(__dirname,'./wrapper.js')); | ||
path = require('path'), | ||
fs = require('fs'), | ||
PermError = 'Permission Denied. Requires administrative privileges.', | ||
wincmd = require('./binaries'), | ||
Logger = require('./eventlog'), | ||
daemonDir = 'daemon', | ||
wrapper = path.resolve(path.join(__dirname, './wrapper.js')); | ||
@@ -45,5 +45,5 @@ // BEGIN SUPER AWFUL HACK TO GET AROUND WINSW.EXE ISSUE! REPLACE ASAP!!!! | ||
// it continues processing with the "install" method. | ||
var sleep = function(period){ | ||
var sleep = function (period) { | ||
var st = new Date().getTime(); | ||
while(new Date().getTime() <= st+(period*1000)){} | ||
while (new Date().getTime() <= st + (period * 1000)) { } | ||
return; | ||
@@ -53,3 +53,3 @@ }; | ||
// The daemon class | ||
var daemon = function(config){ | ||
var daemon = function (config) { | ||
@@ -86,3 +86,3 @@ /** | ||
*/ | ||
Object.defineProperties(this,{ | ||
Object.defineProperties(this, { | ||
_name: { | ||
@@ -95,3 +95,3 @@ enumerable: false, | ||
_eventlog:{ | ||
_eventlog: { | ||
enumerable: false, | ||
@@ -105,6 +105,6 @@ writable: true, | ||
enumerable: false, | ||
get: function(){ | ||
get: function () { | ||
var wrapperArgs = [ | ||
'--file', this.script, | ||
'--scriptoptions='+this.scriptOptions, | ||
'--scriptoptions=' + this.scriptOptions, | ||
'--log', this.name + ' ' + 'wrapper', | ||
@@ -114,8 +114,7 @@ '--grow', this.grow, | ||
'--maxrestarts', this.maxRestarts, | ||
'--abortonerror', (this.abortOnError==true?'y':'n'), | ||
'--abortonerror', (this.abortOnError == true ? 'y' : 'n'), | ||
'--stopparentfirst', this.stopparentfirst | ||
]; | ||
if (this.maxRetries!==null) | ||
{ | ||
if (this.maxRetries !== null) { | ||
wrapperArgs.push('--maxretries'); | ||
@@ -149,4 +148,4 @@ wrapperArgs.push(this.maxRetries); | ||
enumerable: false, | ||
get: function(){ | ||
return this.id+'.exe'; | ||
get: function () { | ||
return this.id + '.exe'; | ||
} | ||
@@ -175,3 +174,3 @@ }, | ||
configurable: false, | ||
value: config.hasOwnProperty('stopparentfirst') ? config.stopparentfirst : false | ||
value: config.stopparentfirst | ||
}, | ||
@@ -192,3 +191,3 @@ | ||
/** | ||
* @cfg {string} [nodeOptions] | ||
* @cfg {string} [nodeOptions='--harmony'] | ||
* Options to be passed to the node process. | ||
@@ -200,9 +199,9 @@ */ | ||
configurable: false, | ||
value: config.nodeOptions | ||
value: config.nodeOptions || '--harmony' | ||
}, | ||
/** | ||
* @cfg {string} [scriptOptions=''] | ||
* Options to be passed to the script. | ||
*/ | ||
/** | ||
* @cfg {string} [scriptOptions=''] | ||
* Options to be passed to the script. | ||
*/ | ||
scriptOptions: { | ||
@@ -279,10 +278,10 @@ enumerable: true, | ||
configurable: false, | ||
value: function(dir){ | ||
if (this.script == null || this.name == null){ | ||
value: function (dir) { | ||
if (this.script == null || this.name == null) { | ||
throw Error('Script and Name are required but were not provided.'); | ||
} | ||
if (dir){ | ||
if (dir) { | ||
this._directory = path.resolve(dir); | ||
} | ||
return path.resolve(path.join(this._directory,daemonDir)); | ||
return path.resolve(path.join(this._directory, daemonDir)); | ||
} | ||
@@ -297,3 +296,3 @@ }, | ||
enumerable: true, | ||
get: function(){ return this.directory();} | ||
get: function () { return this.directory(); } | ||
}, | ||
@@ -304,3 +303,3 @@ | ||
enumerable: false, | ||
get: function(){ | ||
get: function () { | ||
if (this._eventlog !== null) | ||
@@ -310,3 +309,3 @@ return this._eventlog; | ||
throw 'No name was specified for the service'; | ||
this._eventlog = new Logger(this.name+' Monitor'); | ||
this._eventlog = new Logger(this.name + ' Monitor'); | ||
return this._eventlog; | ||
@@ -335,4 +334,4 @@ } | ||
enumerable: false, | ||
get: function(){return this._name;}, | ||
set: function(value){this._name = value;} | ||
get: function () { return this._name; }, | ||
set: function (value) { this._name = value; } | ||
}, | ||
@@ -343,4 +342,4 @@ | ||
enumerable: true, | ||
get: function(){ | ||
return this.name.replace(/[^\w]/gi,'').toLowerCase(); | ||
get: function () { | ||
return this.name.replace(/[^\w]/gi, '').toLowerCase(); | ||
} | ||
@@ -453,3 +452,3 @@ }, | ||
sudo: { | ||
enumerable:false, | ||
enumerable: false, | ||
writable: true, | ||
@@ -514,18 +513,18 @@ configurable: false, | ||
configurable: false, | ||
value: function(dir){ | ||
if (this.script == null || this.name == null){ | ||
value: function (dir) { | ||
if (this.script == null || this.name == null) { | ||
throw Error('Script and Name are required but were not provided.'); | ||
} | ||
if (this.exists){ | ||
if (this.exists) { | ||
var missing = false; | ||
if (!fs.existsSync(path.join(this.root,this._exe))){ | ||
this.log.warn('The main executable is missing or cannot be found ('+path.join(this.root,this._exe)+')'); | ||
if (!fs.existsSync(path.join(this.root, this._exe))) { | ||
this.log.warn('The main executable is missing or cannot be found (' + path.join(this.root, this._exe) + ')'); | ||
missing = true; | ||
} | ||
if (!fs.existsSync(path.join(this.root,this.id+'.xml'))){ | ||
this.log.warn('The primary configuration file is missing or cannot be found ('+path.join(this.root,this.id+'.xml')+')'); | ||
if (!fs.existsSync(path.join(this.root, this.id + '.xml'))) { | ||
this.log.warn('The primary configuration file is missing or cannot be found (' + path.join(this.root, this.id + '.xml') + ')'); | ||
missing = true; | ||
} | ||
if (missing.length > 0){ | ||
if (missing.length > 0) { | ||
this.emit('invalidinstallation'); | ||
@@ -541,3 +540,3 @@ return; | ||
if (typeof dir === 'function'){ | ||
if (typeof dir === 'function') { | ||
callback = dir; | ||
@@ -549,11 +548,11 @@ dir = null; | ||
// If the output directory does not exist, create it. | ||
fs.exists(dir,function(exists){ | ||
if (!exists){ | ||
fs.exists(dir, function (exists) { | ||
if (!exists) { | ||
fs.mkdirSync(dir); | ||
} | ||
// Write the configuration file | ||
fs.writeFile(path.resolve(dir,me.id+'.xml'),me._xml,function(){ | ||
fs.writeFile(path.resolve(dir, me.id + '.xml'), me._xml, function () { | ||
// Write the exe file | ||
winsw.createExe(me.id,dir,function(){ | ||
me.execute('"'+path.resolve(dir,me._exe)+'" install',function(){ | ||
winsw.createExe(me.id, dir, function () { | ||
me.execute('"' + path.resolve(dir, me._exe) + '" install', function () { | ||
sleep(2); | ||
@@ -602,7 +601,7 @@ me.emit('install'); | ||
writable: false, | ||
value: function(waitTime){ | ||
value: function (waitTime) { | ||
var me = this; | ||
waitTime = waitTime || 2; // The same wait time as in the install method | ||
if (!this.exists){ | ||
if (!this.exists) { | ||
console.log('Uninstall was skipped because process does not exist or could not be found.'); | ||
@@ -613,15 +612,15 @@ this.emit('alreadyuninstalled'); | ||
var uninstaller = function(){ | ||
var uninstaller = function () { | ||
// Uninstall the process | ||
me.execute('"'+path.resolve(me.root,me._exe)+'" uninstall',function(error,stdout,stderr){ | ||
if (error){ | ||
me.execute('"' + path.resolve(me.root, me._exe) + '" uninstall', function (error, stdout, stderr) { | ||
if (error) { | ||
me.checkPermError(error); | ||
} else if (stderr.trim().length > 0){ | ||
console.log('Error: ',stderr); | ||
} else if (stderr.trim().length > 0) { | ||
console.log('Error: ', stderr); | ||
} else { | ||
sleep(waitTime); // Wait for uninstall to fully finish | ||
var rm = function(file){ | ||
if (fs.existsSync(path.join(me.root,file))){ | ||
fs.unlinkSync(path.join(me.root,file)); | ||
var rm = function (file) { | ||
if (fs.existsSync(path.join(me.root, file))) { | ||
fs.unlinkSync(path.join(me.root, file)); | ||
} | ||
@@ -631,12 +630,12 @@ }; | ||
// Remove the daemon files individually to prevent security warnings. | ||
rm(me.id+'.xml'); | ||
rm(me.id + '.xml'); | ||
// Remove known wrappers | ||
rm(me.id+'.wrapper.log'); | ||
rm(me.id+'.out.log'); | ||
rm(me.id+'.err.log'); | ||
rm(me.id + '.wrapper.log'); | ||
rm(me.id + '.out.log'); | ||
rm(me.id + '.err.log'); | ||
// Remove the executable and executable .NET runtime config file | ||
rm(me.id+'.exe'); | ||
rm(me.id+'.exe.config'); | ||
rm(me.id + '.exe'); | ||
rm(me.id + '.exe.config'); | ||
@@ -648,3 +647,3 @@ // Remove all other files | ||
}) | ||
_other_files.forEach(function(f){ | ||
_other_files.forEach(function (f) { | ||
rm(f) | ||
@@ -655,4 +654,4 @@ }); | ||
if (fs.readdirSync(me.root).length === 0) { | ||
if (me.root !== path.dirname(me.script)){ | ||
fs.rmdir(me.root,function(){ | ||
if (me.root !== path.dirname(me.script)) { | ||
fs.rmdir(me.root, function () { | ||
sleep(1); | ||
@@ -672,4 +671,4 @@ me.emit('uninstall'); | ||
this.once('stop',uninstaller); | ||
this.once('alreadystopped',uninstaller); | ||
this.once('stop', uninstaller); | ||
this.once('alreadystopped', uninstaller); | ||
this.stop(); | ||
@@ -691,24 +690,24 @@ } | ||
configurable: false, | ||
value: function(){ | ||
value: function () { | ||
var me = this; | ||
if (this.name == null){ | ||
if (this.name == null) { | ||
throw "A name for the service is required."; | ||
} | ||
if (!this.exists){ | ||
throw Error('The service "'+this.name+'" does not exist or could not be found.'); | ||
if (!this.exists) { | ||
throw Error('The service "' + this.name + '" does not exist or could not be found.'); | ||
} | ||
this.execute('NET START "'+me._exe+'"',function(err,stdout,stderr){ | ||
if (err){ | ||
if (err.code == 2){ | ||
if (err.message.indexOf('already been started') >= 0 && err.message.indexOf('service name is invalid') < 0){ | ||
this.execute('NET START "' + me._exe + '"', function (err, stdout, stderr) { | ||
if (err) { | ||
if (err.code == 2) { | ||
if (err.message.indexOf('already been started') >= 0 && err.message.indexOf('service name is invalid') < 0) { | ||
me.log.warn('An attempt to start the service failed because the service is already running. The process should be stopped before starting, or the restart method should be used.'); | ||
me.emit('error',err); | ||
me.emit('error', err); | ||
return; | ||
} else if (err.message.indexOf('service name is invalid') < 0){ | ||
} else if (err.message.indexOf('service name is invalid') < 0) { | ||
me.checkPermError(err); | ||
console.log(err); | ||
me.emit('error',err); | ||
me.emit('error', err); | ||
return; | ||
@@ -737,8 +736,8 @@ } | ||
writable: false, | ||
value: function(){ | ||
value: function () { | ||
var me = this; | ||
me.execute('NET STOP "'+me._exe+'"',function(err,stdout,stderr){ | ||
if (err){ | ||
if (err.code == 2){ | ||
me.execute('NET STOP "' + me._exe + '"', function (err, stdout, stderr) { | ||
if (err) { | ||
if (err.code == 2) { | ||
me.log.warn('An attempt to stop the service failed because the service is/was not running.'); | ||
@@ -765,5 +764,5 @@ me.emit('alreadystopped'); | ||
writable: false, | ||
value: function(callback){ | ||
value: function (callback) { | ||
var me = this; | ||
this.once('stop',me.start); | ||
this.once('stop', me.start); | ||
this.stop(); | ||
@@ -779,7 +778,7 @@ } | ||
enumerable: true, | ||
get: function(){ | ||
if (this.script == null || this.name == null){ | ||
get: function () { | ||
if (this.script == null || this.name == null) { | ||
throw Error('Script and name are required but were not specified.'); | ||
} | ||
return fs.existsSync(path.join(this.directory(),this.id+'.exe')) && fs.existsSync(path.join(this.directory(),this.id+'.xml')) ; | ||
return fs.existsSync(path.join(this.directory(), this.id + '.exe')) && fs.existsSync(path.join(this.directory(), this.id + '.xml')); | ||
} | ||
@@ -793,22 +792,22 @@ }, | ||
configurable: false, | ||
value: function(cmd,options,callback) { | ||
value: function (cmd, options, callback) { | ||
var me = this; | ||
callback = callback || function(){}; | ||
callback = callback || function () { }; | ||
options = options || {}; | ||
wincmd.isAdminUser(function(isAdmin){ | ||
wincmd.isAdminUser(function (isAdmin) { | ||
if (isAdmin) { | ||
if (typeof options === 'function'){ | ||
if (typeof options === 'function') { | ||
callback = options; | ||
options = {}; | ||
} | ||
if (me.user.account !== null && me.user.password !== null){ | ||
_cmd = "runas /profile /user:"+me.user.domain+"\\"+me.user.account+" "+cmd; | ||
exec(cmd,options,callback); | ||
} else if (me.sudo.password !== null){ | ||
if (me.user.account !== null && me.user.password !== null) { | ||
_cmd = "runas /profile /user:" + me.user.domain + "\\" + me.user.account + " " + cmd; | ||
exec(cmd, options, callback); | ||
} else if (me.sudo.password !== null) { | ||
// If the user is not an admin, but a sudo password is provided for admin, | ||
// attempt to launch using sudo. | ||
wincmd.sudo(cmd,me.sudo.password||'',options,callback); | ||
wincmd.sudo(cmd, me.sudo.password || '', options, callback); | ||
} else { | ||
wincmd.elevate(cmd,options,callback) | ||
wincmd.elevate(cmd, options, callback) | ||
} | ||
@@ -828,7 +827,7 @@ } else { | ||
configurable: false, | ||
value: function(error){ | ||
if (error.message.indexOf('Administrator access') >= 0 || error.message.indexOf('Access is denied') >= 0){ | ||
try {this.log.error(PermError);} catch(e){console.log(PermError);} | ||
value: function (error) { | ||
if (error.message.indexOf('Administrator access') >= 0 || error.message.indexOf('Access is denied') >= 0) { | ||
try { this.log.error(PermError); } catch (e) { console.log(PermError); } | ||
} else { | ||
try {this.log.error(error.toString());} catch(e) {console.log(error.toString());} | ||
try { this.log.error(error.toString()); } catch (e) { console.log(error.toString()); } | ||
} | ||
@@ -842,8 +841,8 @@ process.exit(1); | ||
var util = require('util'), | ||
EventEmitter = require('events').EventEmitter; | ||
EventEmitter = require('events').EventEmitter; | ||
// Inherit Events | ||
util.inherits(daemon,EventEmitter); | ||
util.inherits(daemon, EventEmitter); | ||
// Export functionality for the module. | ||
module.exports = daemon; | ||
module.exports = daemon; |
@@ -45,13 +45,13 @@ /** | ||
var wincmd = require('./binaries'), | ||
exec = require("child_process").exec, | ||
eventlogs = ['APPLICATION','SYSTEM'], | ||
validtypes = ['ERROR','WARNING','INFORMATION','SUCCESSAUDIT','FAILUREAUDIT']; | ||
exec = require("child_process").exec, | ||
eventlogs = ['APPLICATION', 'SYSTEM'], | ||
validtypes = ['ERROR', 'WARNING', 'INFORMATION', 'SUCCESSAUDIT', 'FAILUREAUDIT']; | ||
// Write a message to the log. This will create the log if it doesn't exist. | ||
var write = function(log,src,type,msg,id,callback){ | ||
var write = function (log, src, type, msg, id, callback) { | ||
var cmd; | ||
if (msg == null) {return}; | ||
if (msg.trim().length == 0) {return}; | ||
if (msg == null) { return }; | ||
if (msg.trim().length == 0) { return }; | ||
msg = msg.replace(/\r\n|\n\r|\r|\n/g, "\f") | ||
@@ -66,8 +66,8 @@ | ||
cmd = "eventcreate /L "+log+" /T "+type+" /SO \""+src+"\" /D \""+msg+"\" /ID "+id; | ||
cmd = "eventcreate /L " + log + " /T " + type + " /SO \"" + src + "\" /D \"" + msg + "\" /ID " + id; | ||
exec(cmd, function(err) { | ||
exec(cmd, function (err) { | ||
if (err && err.message.indexOf("Access is Denied")) { | ||
wincmd.elevate(cmd, callback); | ||
} else if (callback){ | ||
} else if (callback) { | ||
callback(err); | ||
@@ -79,3 +79,3 @@ } | ||
// Basic functionality | ||
var logger = function(config){ | ||
var logger = function (config) { | ||
@@ -91,3 +91,3 @@ config = config || {}; | ||
// Common attributes | ||
Object.defineProperties(this,{ | ||
Object.defineProperties(this, { | ||
@@ -119,7 +119,7 @@ /** | ||
enumerable: true, | ||
get: function(){ | ||
get: function () { | ||
return this._logname.toUpperCase(); | ||
}, | ||
set: function(value) { | ||
if (value){ | ||
set: function (value) { | ||
if (value) { | ||
this._logname = eventlogs.indexOf(value.toUpperCase()) >= 0 ? value.toUpperCase() : 'APPLICATION'; | ||
@@ -144,4 +144,4 @@ } | ||
configurable: false, | ||
value: function(message,code,callback) { | ||
write(this.eventLog,this.source,'INFORMATION',message,code,callback); | ||
value: function (message, code, callback) { | ||
write(this.eventLog, this.source, 'INFORMATION', message, code, callback); | ||
} | ||
@@ -152,3 +152,3 @@ }, | ||
enumerable: false, | ||
get: function(){ | ||
get: function () { | ||
return this.info; | ||
@@ -172,4 +172,4 @@ } | ||
configurable: false, | ||
value: function(message,code,callback) { | ||
write(this.eventLog,this.source,'ERROR',message,code,callback); | ||
value: function (message, code, callback) { | ||
write(this.eventLog, this.source, 'ERROR', message, code, callback); | ||
} | ||
@@ -192,4 +192,4 @@ }, | ||
configurable: false, | ||
value: function(message,code,callback) { | ||
write(this.eventLog,this.source,'WARNING',message,code,callback); | ||
value: function (message, code, callback) { | ||
write(this.eventLog, this.source, 'WARNING', message, code, callback); | ||
} | ||
@@ -200,3 +200,3 @@ }, | ||
enumerable: false, | ||
get: function(){return this.warn;} | ||
get: function () { return this.warn; } | ||
}, | ||
@@ -218,4 +218,4 @@ | ||
configurable: false, | ||
value: function(message,code,callback) { | ||
write(this.eventLog,this.source,'SUCCESSAUDIT',message,code,callback); | ||
value: function (message, code, callback) { | ||
write(this.eventLog, this.source, 'SUCCESSAUDIT', message, code, callback); | ||
} | ||
@@ -238,4 +238,4 @@ }, | ||
configurable: false, | ||
value: function(message,code,callback) { | ||
write(this.eventLog,this.source,'FAILUREAUDIT',message,code,callback); | ||
value: function (message, code, callback) { | ||
write(this.eventLog, this.source, 'FAILUREAUDIT', message, code, callback); | ||
} | ||
@@ -246,2 +246,2 @@ } | ||
module.exports = logger; | ||
module.exports = logger; |
@@ -18,3 +18,3 @@ /** | ||
*/ | ||
if (require('os').platform().indexOf('win32') < 0){ | ||
if (require('os').platform().indexOf('win32') < 0) { | ||
throw 'node-windows is only supported on Windows.'; | ||
@@ -28,3 +28,3 @@ } | ||
var commands = require('./cmd'); | ||
for (var item in commands){ | ||
for (var item in commands) { | ||
module.exports[item] = commands[item]; | ||
@@ -35,2 +35,2 @@ } | ||
module.exports.Service = require('./daemon'); | ||
module.exports.EventLogger = require('./eventlog'); | ||
module.exports.EventLogger = require('./eventlog'); |
@@ -77,2 +77,3 @@ module.exports = { | ||
xml.push({argument:config.script.trim()}); | ||
console.log({loc: 'winsw.js ~line 77', xml, config}) | ||
multi('argument',config.wrapperArgs,' '); | ||
@@ -105,3 +106,3 @@ | ||
} | ||
// Optionally set the stoptimeout | ||
@@ -108,0 +109,0 @@ if (config.stoptimeout) { |
@@ -0,120 +1,91 @@ | ||
const { errorMonitor } = require('events'); | ||
// Handle input parameters | ||
var Logger = require('./eventlog'), | ||
Args = require('@author.io/args'), | ||
net = require('net'), | ||
max = 60, | ||
p = require('path'), | ||
fork = require('child_process').fork, | ||
attempts = 0, | ||
startTime = null, | ||
starts = 0, | ||
child = null, | ||
forcekill = false; | ||
optimist = require('yargs'), | ||
net = require('net'), | ||
max = 60, | ||
p = require('path'), | ||
fs = require('fs'), | ||
argv = optimist | ||
.demand('file') | ||
.alias('f', 'file') | ||
.describe('file', 'The absolute path of the script to be run as a process.') | ||
.check(function (argv) { | ||
var exists = fs.existsSync(p.resolve(argv.f)) | ||
if (!exists) { | ||
throw new Error(argv.f + ' does not exist or cannot be found.') | ||
} | ||
return true | ||
}) | ||
.describe('scriptoptions', 'The options to be sent to the script.') | ||
.alias('d', 'cwd') | ||
.describe('cwd', 'The absolute path of the current working directory of the script to be run as a process.') | ||
// .check(function(argv){ | ||
// require('fs').existsSync(p.resolve(argv.d),function(exists){ | ||
// return exists; | ||
// }); | ||
// }) | ||
.demand('log') | ||
.alias('l', 'log') | ||
.describe('log', 'The descriptive name of the log for the process') | ||
.default('eventlog', 'APPLICATION') | ||
.alias('e', 'eventlog') | ||
.describe('eventlog', 'The event log container. This must be APPLICATION or SYSTEM.') | ||
.default('maxretries', -1) | ||
.alias('m', 'maxretries') | ||
.describe('maxretries', 'The maximim number of times the process will be auto-restarted.') | ||
.default('maxrestarts', 5) | ||
.alias('r', 'maxrestarts') | ||
.describe('maxrestarts', 'The maximim number of times the process should be restarted within a ' + max + ' second period shutting down.') | ||
.default('wait', 1) | ||
.alias('w', 'wait') | ||
.describe('wait', 'The number of seconds between each restart attempt.') | ||
// .check(function (argv) { | ||
// return argv.w >= 0; | ||
// }) | ||
.default('grow', .25) | ||
.alias('g', 'grow') | ||
.describe('grow', 'A percentage growth rate at which the wait time is increased.') | ||
// .check(function (argv) { | ||
// return (argv.g >= 0 && argv.g <= 1); | ||
// }) | ||
.default('abortonerror', 'no') | ||
.alias('a', 'abortonerror') | ||
.describe('abortonerror', 'Do not attempt to restart the process if it fails with an error,') | ||
.check(function (argv) { | ||
return ['y', 'n', 'yes', 'no'].indexOf(argv.a.trim().toLowerCase()) >= 0; | ||
}) | ||
.default('stopparentfirst', 'no') | ||
.alias('s', 'stopparentfirst') | ||
.describe('stopparentfirst', 'Allow the script to exit using a shutdown message.') | ||
.check(function (argv) { | ||
return ['y', 'n', 'yes', 'no'].indexOf(argv.a.trim().toLowerCase()) >= 0; | ||
}) | ||
.parse(), | ||
log = new Logger(argv.e == undefined ? argv.l : { source: argv.l, eventlog: argv.e }), | ||
fork = require('child_process').fork, | ||
script = p.resolve(argv.f), | ||
wait = argv.w * 1000, | ||
grow = argv.g + 1, | ||
attempts = 0, | ||
startTime = null, | ||
starts = 0, | ||
child = null | ||
forcekill = false; | ||
Args.configure({ | ||
file: { | ||
type: 'string', | ||
required: true, | ||
alias: 'f', | ||
description: 'The absolute path of the script to be run as a process.', | ||
validate: function(value){ | ||
require('fs').existsSync(p.resolve(value),function(exists){ | ||
return exists; | ||
}); | ||
} | ||
}, | ||
scriptoptions: { | ||
type: 'string', | ||
description: 'The options to be sent to the script.' | ||
}, | ||
cwd: { | ||
type: 'string', | ||
description: 'The absolute path of the current working directory of the script to be run as a process.', | ||
alias: 'd', | ||
validate: function(value){ | ||
require('fs').existsSync(p.resolve(value),function(exists){ | ||
return exists; | ||
}); | ||
} | ||
}, | ||
log: { | ||
type: 'string', | ||
required: true, | ||
alias: 'l', | ||
description: 'The descriptive name of the log for the process' | ||
}, | ||
eventlog: { | ||
type: 'string', | ||
alias: 'e', | ||
description: 'The event log container. This must be APPLICATION or SYSTEM.', | ||
defaults: 'APPLICATION' | ||
}, | ||
maxretries: { | ||
type: 'number', | ||
alias: 'm', | ||
description: 'The maximim number of times the process will be auto-restarted.', | ||
defaults: -1 | ||
}, | ||
maxrestarts: { | ||
type: 'number', | ||
alias: 'r', | ||
description: 'The maximim number of times the process should be restarted within a '+max+' second period shutting down.', | ||
defaults: 5 | ||
}, | ||
wait: { | ||
type: 'number', | ||
alias: 'w', | ||
description: 'The number of seconds between each restart attempt.', | ||
defaults: 1, | ||
validate: function(value){ | ||
return value >= 0; | ||
} | ||
}, | ||
grow: { | ||
type: 'number', | ||
alias: 'g', | ||
description: 'A percentage growth rate at which the wait time is increased.', | ||
defaults: .25, | ||
validate: function(value){ | ||
return value >= 0 && value <= 1; | ||
} | ||
}, | ||
abortonerror: { | ||
type: 'string', | ||
alias: 'a', | ||
description: 'Do not attempt to restart the process if it fails with an error.', | ||
defaults: 'no', | ||
options: ['y','n','yes','no'] | ||
}, | ||
stopparentfirst: { | ||
type: 'string', | ||
alias: 's', | ||
decribe: 'Allow the script to exit using a shutdown message.', | ||
defaults: 'no', | ||
options: ['y','n','yes','no'] | ||
} | ||
}); | ||
Args.disallowUnrecognized(); | ||
Args.enforceRules(); | ||
var argv = Args.data, | ||
log = new Logger(argv.eventlog == undefined ? argv.log : {source:argv.log,eventlog:argv.eventlog}), | ||
script = p.resolve(argv.file), | ||
wait = argv.wait*1000, | ||
grow = argv.grow+1; | ||
if (argv.cwd){ | ||
if (!require('fs').existsSync(p.resolve(argv.cwd))){ | ||
console.warn(argv.cwd+' not found.'); | ||
argv.cwd = process.cwd(); | ||
if (argv.d) { | ||
if (!require('fs').existsSync(p.resolve(argv.d))) { | ||
console.warn(argv.d + ' not found.'); | ||
argv.d = process.cwd(); | ||
} | ||
argv.cwd = p.resolve(argv.cwd); | ||
argv.d = p.resolve(argv.d); | ||
} | ||
if (typeof argv.maxretries === 'string'){ | ||
argv.maxretries = parseInt(argv.maxretries); | ||
if (typeof argv.m === 'string') { | ||
argv.m = parseInt(argv.m); | ||
} | ||
// Set the absolute path of the file | ||
argv.file = p.resolve(argv.file); | ||
argv.f = p.resolve(argv.f); | ||
@@ -125,4 +96,4 @@ // Hack to force the wrapper process to stay open by launching a ghost socket server | ||
server.on('error', function (err) { | ||
launch('warn', err.message); | ||
server = net.createServer().listen(); | ||
launch('warn', err.message); | ||
server = net.createServer().listen(); | ||
}); | ||
@@ -134,9 +105,9 @@ | ||
*/ | ||
var monitor = function() { | ||
if(!child || !child.pid) { | ||
var monitor = function () { | ||
if (!child || !child.pid) { | ||
// If the number of periodic starts exceeds the max, kill the process | ||
if (starts >= argv.maxrestarts){ | ||
if (new Date().getTime()-(max*1000) <= startTime.getTime()){ | ||
log.error('Too many restarts within the last '+max+' seconds. Please check the script.'); | ||
if (starts >= argv.r) { | ||
if (new Date().getTime() - (max * 1000) <= startTime.getTime()) { | ||
log.error('Too many restarts within the last ' + max + ' seconds. Please check the script.'); | ||
process.exit(); | ||
@@ -146,7 +117,7 @@ } | ||
setTimeout(function(){ | ||
setTimeout(function () { | ||
wait = wait * grow; | ||
attempts += 1; | ||
if (attempts > argv.maxretries && argv.maxretries >= 0){ | ||
log.error('Too many restarts. '+argv.file+' will not be restarted because the maximum number of total restarts has been exceeded.'); | ||
if (attempts > argv.m && argv.m >= 0) { | ||
log.error('Too many restarts. ' + argv.f + ' will not be restarted because the maximum number of total restarts has been exceeded.'); | ||
process.exit(); | ||
@@ -156,7 +127,7 @@ } else { | ||
} | ||
},wait); | ||
}, wait); | ||
} else { | ||
// reset attempts and wait time | ||
attempts = 0; | ||
wait = argv.wait * 1000; | ||
wait = argv.w * 1000; | ||
} | ||
@@ -172,4 +143,3 @@ }; | ||
*/ | ||
var launch = function(logLevel, msg) { | ||
var launch = function (logLevel, msg) { | ||
if (forcekill) { | ||
@@ -180,3 +150,3 @@ log.info("Process killed"); | ||
//log.info('Starting '+argv.file); | ||
//log.info('Starting '+argv.f); | ||
if (logLevel && msg) { | ||
@@ -189,6 +159,6 @@ log[logLevel](msg); | ||
startTime = startTime || new Date(); | ||
setTimeout(function(){ | ||
setTimeout(function () { | ||
startTime = null; | ||
starts = 0; | ||
},(max*1000)+1); | ||
}, (max * 1000) + 1); | ||
} | ||
@@ -198,16 +168,16 @@ starts += 1; | ||
// Fork the child process | ||
var opts = {env:process.env}; | ||
var opts = { env: process.env }; | ||
var args = []; | ||
if (argv.cwd) opts.cwd = argv.cwd; | ||
if (argv.stopparentfirst) opts.detached = true; | ||
if (argv.d) opts.cwd = argv.d; | ||
if (argv.s) opts.detached = true; | ||
if (argv.scriptoptions) args = argv.scriptoptions.split(' '); | ||
child = fork(script,args,opts); | ||
child = fork(script, args, opts); | ||
// When the child dies, attempt to restart based on configuration | ||
child.on('exit',function(code){ | ||
log.warn(argv.file+' stopped running.'); | ||
child.on('exit', function (code) { | ||
log.warn(argv.f + ' stopped running.'); | ||
// If an error is thrown and the process is configured to exit, then kill the parent. | ||
if (code !== 0 && argv.abortonerror == "yes"){ | ||
log.error(argv.file+' exited with error code '+code); | ||
if (code !== 0 && argv.a == "yes") { | ||
log.error(argv.f + ' exited with error code ' + code); | ||
process.exit(); | ||
@@ -225,6 +195,6 @@ //server.unref(); | ||
var killkid = function(){ | ||
var killkid = function () { | ||
forcekill = true; | ||
if (child) { | ||
if (argv.stopparentfirst) { | ||
if (argv.s) { | ||
child.send('shutdown'); | ||
@@ -235,3 +205,3 @@ } else { | ||
} else { | ||
log.warn('Attempted to kill an unrecognized process.'); | ||
log.warn('Attempted to kill an unrecognized process.') | ||
} | ||
@@ -244,7 +214,7 @@ } | ||
process.on('uncaughtException', function(err) { | ||
launch('warn', err.message); | ||
process.on('uncaughtException', function (err) { | ||
launch('warn', err.message); | ||
}); | ||
// Launch the process | ||
launch('info', 'Starting ' + argv.file); | ||
launch('info', 'Starting ' + argv.f); |
{ | ||
"name": "node-windows", | ||
"version": "1.0.0-beta.7", | ||
"version": "1.0.0-beta.8", | ||
"description": "Support for Windows services, event logging, UAC, and several helper methods for interacting with the OS.", | ||
@@ -21,4 +21,4 @@ "keywords": [ | ||
"dependencies": { | ||
"@author.io/arg": "1.3.22", | ||
"xml": "1.0.1" | ||
"xml": "1.0.1", | ||
"yargs": "^17.5.1" | ||
}, | ||
@@ -25,0 +25,0 @@ "readmeFilename": "README.md", |
# node-windows | ||
![NPM version](https://img.shields.io/npm/v/node-windows?label=node-windows&logo=npm&style=for-the-badge) | ||
![NGN Dependencies](https://david-dm.org/coreybutler/node-windows.svg?style=for-the-badge) | ||
![NGN Dependencies](https://img.shields.io/librariesio/release/npm/node-windows?style=for-the-badge) | ||
@@ -6,0 +6,0 @@ [Tweet me (@goldglovecb)](http://twitter.com/goldglovecb) if you need me. |
179675
7
1498
+ Addedyargs@^17.5.1
+ Addedansi-regex@5.0.1(transitive)
+ Addedansi-styles@4.3.0(transitive)
+ Addedcliui@8.0.1(transitive)
+ Addedcolor-convert@2.0.1(transitive)
+ Addedcolor-name@1.1.4(transitive)
+ Addedemoji-regex@8.0.0(transitive)
+ Addedescalade@3.1.2(transitive)
+ Addedget-caller-file@2.0.5(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedrequire-directory@2.1.1(transitive)
+ Addedstring-width@4.2.3(transitive)
+ Addedstrip-ansi@6.0.1(transitive)
+ Addedwrap-ansi@7.0.0(transitive)
+ Addedy18n@5.0.8(transitive)
+ Addedyargs@17.7.2(transitive)
+ Addedyargs-parser@21.1.1(transitive)
- Removed@author.io/arg@1.3.22
- Removed@author.io/arg@1.3.22(transitive)