Skip to content

Instantly share code, notes, and snippets.

@brettz9
Created October 29, 2009 04:36
Show Gist options
  • Select an option

  • Save brettz9/221159 to your computer and use it in GitHub Desktop.

Select an option

Save brettz9/221159 to your computer and use it in GitHub Desktop.
// As a function or class, the following can be used to execute
// command-line programs from Firefox. When used with executing
// a batch file with arguments as at
// http://gist.github.com/221161/ , Firefox can be made to pipe
// success or error output to a file and then retrieve the file
// (e.g., to make a FF extension which works as a command-line,
// allowing copy-and-paste, logging, etc.)
/**
* Execute a file on the command line with the given arguments
* @param {String} fileStr File in native format (e.g., "C:\\Users\\Brett")
* @param {String[]} args Array of arguments to pass to the file
* @returns {String} Process ID
*/
function run (fileStr, args) {
var file = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(fileStr);
var p = Components.classes["@mozilla.org/process/util;1"]
.createInstance(Components.interfaces.nsIProcess);
p.init(file);
p.run(false, args, args.length);
return p.pid; // Can't use anymore, but does return in Windows at least
}
/**
* Set up a Processor object
* @class methods for executing command line executables
* @param {String} fileStr The default file to use for executing processes
*/
function Processor (fileStr) {
this.fileStr = fileStr;
}
/**
* Wrap the arguments into an array
* @private
* @param {String[]|String|null|undefined} args The arguments (if any) to wrap
*/
Processor.prototype._wrapArgs = function (args) {
if (!args) {
args = [];
}
else if (typeof args === 'string') {
args = [args];
}
return args;
};
/**
* Accept an nsIProcess or nsIProcess2 instance and use it with a file stored on the object to initialize a
* process; also passes through and wraps arguments
* @private
* @param {Components.interfaces.nsIProcess|Components.interfaces.nsIProcess2} p
* @param {String[]|String|null|undefined} args The arguments (if any) to wrap
* @x-todo This should ideally be able to do more than just initWithPath, e.g., accept nsIFile, etc. (as determined
* configurably by esp. the constructor)
*/
Processor.prototype._runHelper = function (p, args) {
var file = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(this.fileStr);
p.init(file);
return this._wrapArgs(args);
};
Processor.prototype._asyncHelper = function (args, observerObj, holdWeak) {
var p = Components.classes["@mozilla.org/process/util;1"].
createInstance(Components.interfaces.nsIProcess2);
args = this._runHelper(p, args);
p.runAsync(args, args.length, observerObj, holdWeak || false);
};
/**
* Run an executable with optional arguments asynchronously, triggering a single callback upon completion or failure
* @param {String[]|String|null|undefined} args The arguments (if any) to wrap and pass to the file
* @param {Components.interfaces.nsIObserver} [observer] The Observer to be notified of progress of process
* (can be an object or just a function that accepts the
* observer arguments); called on main thread
* 1) Takes nsIProcess2 as subject
* 2) 'process-finished' or 'process-failed' as topic
* @param {Boolean} [holdWeak] Whether or not to use a weak reference to the observer (default is false)
* @example
var p = new Processor('C:\\someFile');
p.runAsync([], {observe:
function (subject, topic, data) {
if (topic==='process-finished') {
alert('finished process');
}
else if (topic === 'process-failed') {
alert('failed process');
}
}
}, true);
*/
Processor.prototype.runAsync = function (args, observer, holdWeak) {
var observerObj = observer || null;
if (typeof observer === 'function') {
observerObj = {observe: observer};
}
this._asyncHelper(args, observerObj, holdWeak);
};
/**
* Run an executable with optional arguments asynchronously, triggering different callbacks upon completion or failure
* @param {String[]|String|null|undefined} args The arguments (if any) to wrap and pass to the file
* @param {Function} [cbFinished] The callback to be notified of completion of process; called on main thread; passed
* the following arguments:
* 1) nsIProcess2 (subject)
* 2) data
* @param {Function} [cbFailed] The callback to be notified of failure of process; called on main thread; passed
* the following arguments:
* 1) nsIProcess2 (subject)
* 2) data
* @param {Boolean} [holdWeak] Whether or not to use a weak reference to the observer (default is false)
* @example
var p = new Processor('C:\\someFile');
p.runAsync([],
function (subject, data) {
alert('finished process');
},
function (subject, data) {
alert('failed process');
}
}, true);
*/
Processor.prototype.runAsyncUtil = function (args, cbFinished, cbFailed, holdWeak) {
if (cbFinished || cbFailed) {
cbFinished = cbFinished || function (subject, data, topic) {};
cbFailed = cbFailed || function (subject, data, topic) {};
var observerObj = {observe:
function (subject, topic, data) {
// Topic moved as last argument to callbacks since we don't need it (we already know what it is)
if (topic==='process-finished') {
cbFinished(subject, data, topic);
}
else if (topic === 'process-failed') {
cbFailed(subject, data, topic);
}
}
};
}
this._asyncHelper(args, observerObj, holdWeak);
};
/**
* Execute a command line executable file with a given argument or arguments (if any)
* @param {String[]|String|null|undefined} args The arguments (if any) to wrap and pass to the file
* @returns {String} Process ID (Can't use this within nsIProcess anymore, but does return in Windows at least)
*/
Processor.prototype.run = function (args) {
var p = Components.classes["@mozilla.org/process/util;1"]
.createInstance(Components.interfaces.nsIProcess);
args = this._runHelper(p, args);
p.run(false, args, args.length);
return p.pid;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment