diff --git a/README.md b/README.md index 9c69b44..9cefc38 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,23 @@ -# wintools - Some windows tools for node.js # +# wintools - Some windows tools for node.js + +## Installation ```bash npm install wintools ``` - * __ps(callback)__ where callback is `function(err, list)` returns a list of running processes. - * __kill.pid(pid, callback)__ kills a process by PID. - * __kill.image(imageName, callback)__ kills a process by image name (e.g. `node.exe`). - * __shutdown.poweroff([callback])__ turns of off the machine immediately. - * __shutdown.restart([callback])__ rstarts the machine immediately. +```javascript +var wintools = require('wintools'); +``` + +## API + + * `wintools.ps(options, callback)` where callback is `function(err, list)` returns a list of running processes. + * `wintools.kill.pid(pid, callback)` kills a process by PID. + * `wintools.kill.image(imageName, callback)` kills a process by image name (e.g. `node.exe`). + * `wintools.shutdown.poweroff([callback])` turns of off the machine immediately. + * `wintools.shutdown.restart([callback])` rstarts the machine immediately. -## License ## +## License MIT \ No newline at end of file diff --git a/lib/kill.js b/lib/kill.js index 9c3146d..e4edab0 100644 --- a/lib/kill.js +++ b/lib/kill.js @@ -1,40 +1,52 @@ -var exec = require('child_process').exec; - +var exec = require('child_process').exec; + /** - * Kills a process by PID. - * @param pid Required. Process ID. - * @param callback Optional. - * @remarks Windows only - */ -exports.pid = function(pid, callback) { - if (!pid) throw new Error('pid is required'); - if (!callback) callback = function() {}; - - exec('taskkill /t /f /pid ' + pid.toString(), function (err, stdout, stderr) { - if (err) { - callback({ msg: "unable to kill " + pid, err: err, stdout: stdout, stderr: stderr }); - return; - } - - callback(); - }); -}; - +* Kills a process by PID. +* @param pid Required. Process ID. +* @param callback Optional. +* @remarks Windows only +*/ +exports.pid = function (pid, callback) { + if (!pid) throw new Error('pid is required'); + if (!callback) callback = function () { }; + + exec('taskkill /t /f /pid ' + pid.toString(), function (err, stdout, stderr) { + if (err) { + callback({ msg: "unable to kill " + pid, err: err, stdout: stdout, stderr: stderr }); + return; + } + + callback(); + }); +}; + /** - * Kills all the processes with the specified image name - * @param imageName Required. The name of the image (e.g. 'node.exe') - * @param callback Optional. - */ -exports.image = function(imageName, callback) { - if (!imageName) throw new Error('imageName is required'); - if (!callback) callback = function() {}; - - exec('taskkill /t /f /im ' + imageName, function (err, stdout, stderr) { - if (err) { - callback({ msg: "unable to kill " + imageName, err: err, stdout: stdout, stderr: stderr }); - return; - } - - callback(); - }); +* Kills all the processes with the specified image name +* @param imageName Required. The name of the image (e.g. 'node.exe') +* @param callback Optional. +*/ +exports.image = function (imageName, opts, callback) { + if (!imageName) throw new Error('imageName is required'); + + if (typeof opts === 'function') { + callback = opts; + opts = ''; + } + + if (!opts) { + opts = ''; + } + + if (!callback) callback = function () { }; + + var cmd = ('taskkill /t /f /im ' + imageName + ' ' + opts).trim(); + console.log('cmd:', cmd); + exec(cmd, function (err, stdout, stderr) { + if (err) { + callback({ msg: "unable to kill " + imageName, err: err, stdout: stdout, stderr: stderr }); + return; + } + + callback(); + }); } diff --git a/lib/ps.js b/lib/ps.js index 2b6b971..684b56d 100644 --- a/lib/ps.js +++ b/lib/ps.js @@ -1,48 +1,69 @@ -var exec = require('child_process').exec; - +var spawn = require('child_process').spawn; +var xml2js = require('xml2js'); + /** - * Returns all the system processes - * @param callback {function(err, list)} Called with the list of all processes. - * @remarks Runs only on Windows (uses WMI) - */ -module.exports = function(callback) { - if (!callback) callback = function(err, list) { }; - - exec('wmic process list /format:csv', function (err, stdout, stderr) { - if (err) { - callback({ err: err, msg: "unable to enumerate processes" }); - return; - } - - stdout = stdout.replace(/\r/g, '').split('\n').slice(1); - fields = stdout.shift().split(','); - - var output = {}; - stdout.forEach(function (line) { - - var parts = line.split(','); - var entry = {}; - for (var i = 0; i < fields.length; ++i) { - entry[fields[i]] = parts[i]; - } - - var e = { - pid: entry.Handle, - desc: entry.Description, - cmd: entry.CommandLine, - prog: entry.ExecutablePath, - workingSet: entry.WorkingSetSize, - }; - - // remove some empty stuff - if (!e.cmd) delete e.cmd; - if (!e.prog) delete e.prog; - - if (e.pid) { - output[e.pid] = e; - } - }); - - callback(null, output); - }); +* Returns all the system processes +* @param options +* filter {function(p)} filters processes before inserting to result list. +* @param callback {function(err, list)} Called with the list of all processes. +* @remarks Runs only on Windows (uses WMI) +*/ +module.exports = function (options, callback) { + + if (typeof options === 'function') { + callback = options; + options = {}; + } + + options = options || {}; + options.filter = options.filter || function () { return true; }; + + callback = callback || function () { }; + + var cmd = [ + 'process', + 'list', + '/format:rawxml' + ]; + + // Spawn process, since output from exec can be too big for buffer size supported. + var p = spawn('wmic', cmd); + + var xml = ''; + + p.stdout.on('data', function (data) { + xml = xml + data.toString(); + }); + + p.stderr.on('data', function (data) { + console.error(data); + }); + + p.on('exit', function () { + parser = new xml2js.Parser(); + parser.parseString(xml, function (err, result) { + var output = {}; + result.RESULTS.CIM.INSTANCE.forEach(function (p) { + var entry = {}; + p.PROPERTY.forEach(function (v) { + entry[v['@'].NAME] = v.VALUE; + }); + + var e = { + pid: entry.Handle, + desc: entry.Description, + cmd: entry.CommandLine, + prog: entry.ExecutablePath + }; + + if (!e.cmd) delete e.cmd; + if (!e.prog) delete e.prog; + + if (e.pid && options.filter(e)) { + output[e.pid] = e; + } + }); + callback(null, output); + }); + }); } \ No newline at end of file diff --git a/package.json b/package.json index a8b72a0..28faba5 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,35 @@ { - "name": "wintools", - "description": "Some Windows tools for node.js", - "main": "./main", - "author": "Elad Ben-Israel", - "version": "0.1.0", - "dependencies": { - "async": ">=0.1.15" - }, - "devDependencies": { - "nodeunit": "*" - }, - "repository": { - "type": "git", - "url": "https://github.com/anodejs/node-wintools" - }, - "scripts": { - "test": "node_modules/nodeunit/bin/nodeunit tests/" - } + "name": "wintools", + "description": "Some Windows tools for node.js", + "main": "./main", + "bin": {}, + "author": "anode ", + "version": "0.2.1", + "license": "MIT", + "contributors": [ + "Elad Ben-Israel ", + "Yosef Dinerstein " + ], + "keywords": [ + "nodejs", + "windows" + ], + "engines": { + "node": "~0.6.x" + }, + "dependencies": { + "async": "0.1.x", + "xml2js": "0.1.x" + }, + "devDependencies": { + "nodeunit": "0.6.x" + }, + "repository": { + "type": "git", + "url": "git://github.com/anodejs/node-wintools.git" + }, + "scripts": { + "test": "nodeunit test/*.js" + } } + diff --git a/tests/tests.js b/tests/tests.js index c60f6ff..97101e5 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -1,31 +1,31 @@ -var wintools = require('../main'); - -exports.ps = function(test) { - wintools.ps(function(err, ps) { - test.ok(!err, err); - test.ok(ps); - test.ok(ps && Object.keys(ps).length > 0); - test.done(); - }); -}; - -exports.killByPID = function(test) { - wintools.kill.pid(77777, function(err) { - test.ok(err); - test.done(); - }); -}; - -exports.killByImage = function(test) { - wintools.kill.image('bla.exe', function(err) { - test.ok(err); - test.done(); - }); -}; - -exports.shutdown = function(test) { - // only check that api exists - test.ok(wintools.shutdown.poweroff); - test.ok(wintools.shutdown.restart); - test.done(); +var wintools = require('../main'); + +exports.ps = function (test) { + wintools.ps(function (err, ps) { + test.ok(!err, err); + test.ok(ps); + test.ok(ps && Object.keys(ps).length > 0); + test.done(); + }); +}; + +exports.killByPID = function (test) { + wintools.kill.pid(77777, function (err) { + test.ok(err); + test.done(); + }); +}; + +exports.killByImage = function (test) { + wintools.kill.image('bla.exe', function (err) { + test.ok(err); + test.done(); + }); +}; + +exports.shutdown = function (test) { + // only check that api exists + test.ok(wintools.shutdown.poweroff); + test.ok(wintools.shutdown.restart); + test.done(); }; \ No newline at end of file