How to send CONTROL+C at spawn in nodejs - windows

I run CMD to spawn, but if you'll send me a ping command, I can not get out of it, how can I send the console control + c, to avoid this? THANKS!
var fs = require('fs');
var iconv = require('iconv-lite');
function sendData (msg) {
console.log('write msg ', msg);
cmd.stdin.write(msg + "\r\n");
}
function execCommand() {
console.log('start command line')
var s = {
e : 'exec_command',
d : {
data : {}
}
};
cmd = require('child_process').spawn('cmd', ['/K']);
cmd.stdout.on('data', function (data) {
console.log(iconv.decode(data, 'cp866'));
});
}
execCommand();
sendData('ping e1.ru -t');
sendData( EXIT ??? )
?????
I want to make a console, a full-fledged console through node.js.
sendData('dir');
sendData('cd /d Windows');
sendData('ping 8.8.8.8 -t');
senData( CONTROL + C );
senData('dir')

You'll want to explicitly call:
cmd.kill();
that'll do the trick. If you require the equivalent of CTRL-C then call:
cmd.kill('SIGINT');
See child_process.kill docs for more info.

Related

Collecting Yarn Metrics

I would like to collect metrics on how long yarn commands such as yarn install take to complete and other metrics such as how often the commands don't complete successfully.
My .yarnrc file looks like this:
registry "https://artifactory-content.company.build/artifactory/api/npm/npm"
"--ignore-engines" true
"#sail:registry" "https://artifactory-content.company.build/artifactory/api/npm/npm-local"
"#company-internal:registry" "https://artifactory-content.company.build/artifactory/api/npm/npm-local"
lastUpdateCheck 1617811239383
yarn-path "./yarn-1.19.1.js"
From what I understand, when I run the yarn command, it invokes the yarn-1.19.1.js file. Would it be possible to create a wrapper such that when any yarn command is run, it logs the metrics at the command level and then executes the yarn-1.19.1.js file?
Another approach I ran across was modifying the package.json file and overriding the commands as mentioned here but this doesn't seem scalable as there might be new commands added later on.
Yes, you could create a wrapper script that invokes the Yarn core library. This is exactly what the Node.js that is yarn does:
#!/usr/bin/env node
'use strict';
var ver = process.versions.node;
var majorVer = parseInt(ver.split('.')[0], 10);
if (majorVer < 4) {
console.error('Node version ' + ver + ' is not supported, please use Node.js 4.0 or higher.');
process.exit(1);
} else {
try {
require(__dirname + '/../lib/v8-compile-cache.js');
} catch (err) {
}
var cli = require(__dirname + '/../lib/cli');
if (!cli.autoRun) {
cli.default().catch(function(error) {
console.error(error.stack || error.message || error);
process.exitCode = 1;
});
}
}
You could just edit that script like so:
const start = Date.now();
var cli = require(__dirname + '/../lib/cli');
if (!cli.autoRun) {
cli.default()
.then(function() {
const durationInMs = Date.now() - start;
// It succeeded, do your stuff.
})
.catch(function(error) {
console.error(error.stack || error.message || error);
process.exitCode = 1;
const durationInMs = Date.now() - start;
// It failed, do your stuff.
});
}

Electron open & keep open cmd.exe

I'm building a little tool that should among other thing allow me to start a Tomcat server.
Pretty easy, I just want a button to launch startup.bat and another to call shutdown.bat.
It works quite well (server start and stop) but completely in ninja mode, I can't manage to get the Tomcat console with the logs.
From a classic command line if I call startup.bat, a Window is opened with logs inside.
I tried exec, execFile, spawn. I tried calling directly the bat, the cmd.exe, even tried start. But I can't get the Window.
I know I can get streams, but I would like not to bother with that.
Also I'm just using the tool on Windows, no need to think about other platform for the moment.
const ipc = require('electron').ipcMain;
const execFile = require('child_process').execFile;
ipc.on('start-local-tomcat', function (event) {
execFile('cmd.exe', ['D:\\DEV\\apache-tomcat-8.0.12\\bin\\startup.bat'],
{env: {'CATALINA_HOME': 'D:\\DEV\\apache-tomcat-8.0.12'}},
function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
})
});
ipc.on('stop-local-tomcat', function (event) {
execFile('cmd.exe',['D:\\DEV\\apache-tomcat-8.0.12\\bin\\shutdown.bat'],
{env: {'CATALINA_HOME': 'D:\\DEV\\apache-tomcat-8.0.12'}},
function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
})
});
Finally I just didn't read the doc enough, there is a parameter called detached that will do exactly what I want:
var child = spawn(
'D:\\DEV\\apache-tomcat-8.0.12\\bin\\startup.bat',
{
env: {'CATALINA_HOME': 'D:\\DEV\\apache-tomcat-8.0.12'},
detached: true
}
);

Restify debugging in WebStorm

I'm trying to set up a very basic restify server so I can debug it in WebStorm. I can run the process normally, but when using the debug function in WebStorm the process exits immediately.
My restify server is located in the server.js folder:
var restify = require('restify');
function respond(req, res, next) {
res.send('hello ' + req.params.name);
next();
}
var server = restify.createServer();
server.get('/hello/:name', respond);
server.head('/hello/:name', respond);
server.listen(8080, function() {
console.log('%s listening at %s', server.name, server.url);
});
I would like to hit a breakpoint set inside the respond function.
When I run the solution it starts up normally and I can hit the hello endpoint:
"C:\Program Files (x86)\JetBrains\WebStorm 2016.1.1\bin\runnerw.exe" "C:\Program Files\nodejs\node.exe" server.js
restify listening at http://[::]:8080
However, hitting debug I get :
"C:\Program Files (x86)\JetBrains\WebStorm 2016.1.1\bin\runnerw.exe" "C:\Program Files\nodejs\node.exe" --debug-brk=60036 server.js
Debugger listening on port 60036
Process finished with exit code -1073741819 (0xC0000005)
My local config file looks like this (nothing special):
What am I doing wrong?
EDIT:
I looked at the template which WebStorm generates with express to try and find some inspiration to get debugging to work with restify. Basically I am mimicing the WebStorm template now, so I have an additional file in bin/wwww:
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('test2:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
//app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
Instead of the server file, I use app.js:
var restify = require('restify');
var restifyApp = function () {
var server = restify.createServer({
name: 'myapp',
version: '1.0.0'
});
server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());
server.get('/echo/:name', function (req, res, next) {
res.send(req.params);
return next();
});
};
module.exports = restifyApp;
With this setup I am actually able to start in debug mode. However, as soon as I try http://localhost:3000/echo/hey (as an example), the request times out and once again I get feedback in the terminal with the message Process finished with exit code -1073741819 (0xC0000005)
Looks like Node V8 issue (as debugging also fails when using node-inspector). I was able to debug your code after downgrading to Node.js 0.10.31. Node 4.3 breaks with AccessViolation, Node 5.5 hangs.

Run shell command when render is complete (After Effects)

is there a way to programmatically run a shell command after a render has completed in Adobe After effects?
Execute a command line from After Effects
You can execute a command line with the sysmte.callSystem(cmdLineToExecute) function. Go see the After Effects Scripting Guide page 180 section System callSystem() method.
Here is an exemple whith a echo command : (callSystemreturns the command line return's) :
var commandOutput = system.callSystem("cmd.exe /c echo hi ");
alert(commandOutput);
This will output
hi
What is after /c is the command to execute in the cmd.
A more complex exemple from the scripting guide which get the system time :
var timeStr = system.callSystem("cmd.exe /c \"time /t\"");
alert("Current time is " + timeStr);
This will output
Curent time is 11:28
Open a command line from After Effects
Now if you are looking to open a command line in another window, you have to set the cmdLineToExecute as if you were in a command line.
On windows, if you want to open a command line in another window, you have to do this :
start cmd.exe
So if you want to do it from After
system.callSystem("cmd.exe /c start cmd.exe ");
Open a command line when the render is done in After Effects
This is a mix with #fabiantheblind's answer.
// Create a comp with a solid
var comp = app.project.items.addComp('test', 100, 100, 1, 1, 12);
comp.layers.addSolid([0.5, 0.5, 0.5], 'solid', 100, 100, 1, 1);
// Add the comp to the render queue
var rq_item = app.project.renderQueue.items.add(comp);
rq_item.outputModule(1).file = File('~/Desktop/out.mov');
rq_item.render = true;
// Set a function which will be called every frame when the comp will be rendering
// A boolean to be sure that the function called at the end is called once
var called = false;
rq_item.onStatusChanged = function() {
while (rq_item.status === RQItemStatus.RENDERING) {
// Is rendering...
$.writeln('Rendering');
}
// When the render is finished
if (!called && rq_item.status === RQItemStatus.DONE) {
called = true;
system.callSystem("cmd.exe /c start cmd.exe ");
}
};
// Launch the render
app.project.renderQueue.render();
// If something goes wrong
app.onError = function(err) {
$.writeln('ERROR ' + err);
};
Try this code. The only thing you need to investigate is why the (rq_item.status === RQItemStatus.DONE) gets called twice.
// Create a comp with a solid
var comp = app.project.items.addComp('test', 100, 100, 1, 1, 12);
comp.layers.addSolid([0.5, 0.5, 0.5], 'solid', 100, 100, 1, 1);
// Add the comp to the render queue
var rq_item = app.project.renderQueue.items.add(comp);
rq_item.outputModule(1).file = File('~/Desktop/out.mov');
rq_item.render = true;
// Set a function which will be called every frame when the comp will be rendering
// A boolean to be sure that the function called at the end is called once
var called = false;
rq_item.onStatusChanged = function() {
while (rq_item.status === RQItemStatus.RENDERING) {
// Is rendering...
$.writeln('Rendering');
}
// When the render is finished
if (!called && rq_item.status === RQItemStatus.DONE) {
called = true;
$.writeln('Done rendering');
// test for Mac or Win
var res = null;
if($.os.charAt (0) === 'M'){
res = system.callSystem('echo "Hello Mac World"');
}else{
res = system.callSystem('cmd.exe /c echo "Hello Win World"');
}
$.writeln(res);
}
};
// Launch the render
app.project.renderQueue.render();
// If something goes wrong
app.onError = function(err) {
$.writeln('ERROR ' + err);
};

Using sockets (nsIServerSocket) in XPCOM component (Firefox Extension) (sockets + new window = seg faults)

PLEASE READ THE UPDATE #2 BELOW IF YOU ARE INTERESTED IN THIS PROBLEM ;)
Say I put this code into the JS of my extension.
var reader = {
onInputStreamReady : function(input) {
var sin = Cc["#mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
sin.init(input);
sin.available();
var request = '';
while (sin.available()) {
request = request + sin.read(512);
}
console.log('Received: ' + request);
input.asyncWait(reader,0,0,null);
}
}
var listener = {
onSocketAccepted: function(serverSocket, clientSocket) {
console.log("Accepted connection on "+clientSocket.host+":"+clientSocket.port);
input = clientSocket.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
output = clientSocket.openOutputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0);
input.asyncWait(reader,0,0,null);
}
}
var serverSocket = Cc["#mozilla.org/network/server-socket;1"].
createInstance(Ci.nsIServerSocket);
serverSocket.init(-1, true, 5);
console.log("Opened socket on " + serverSocket.port);
serverSocket.asyncListen(listener);
Then I run Firefox and connect to the socket via telnet
telnet localhost PORT
I send 5 messages and they get printed out, but when I try to send 6th message I get
firefox-bin: Fatal IO error 11 (Resource temporarily unavailable) on X server :0.0.
Even worse, when I try to put this same code into an XPCOM component (because that's where I actually need it), after I try sending a message via telnet I get
Segmentation fault
or sometimes
GLib-ERROR **: /build/buildd/glib2.0-2.24.1/glib/gmem.c:137: failed to allocate 32 bytes
aborting...
Aborted
printed to the terminal from which I launched firefox.
This is really weird stuff.. Can you spot something wrong with the code I've pasted or is smth wrong with my firefox/system or is the nsIServerSocket interface deprecated?
I'm testing with Firefox 3.6.6.
I would really appreciate some answer. Perhaps you could point me to a good example of using Sockets within an XPCOM component. I haven't seen many of those around.
UPDATE
I just realised that it used to work so now I think that my Console
component breaks it. I have no idea how this is related. But if I
don't use this component the sockets are working fine.
Here is the code of my Console component. I will try to figure out
what's wrong and why it interferes and I'll post my findings later.
Likely I'm doing something terribly wrong here to cause Segmentation
faults with my javascript =)
Voodoo..
components/Console.js:
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
Console.prototype = (function() {
var win;
var initialized = false;
var ready = false;
var _log = function(m, level, location) {
if (initialized&&ready) {
var prefix = "INFO: ";
switch (level) {
case "empty":
prefix = ""
break;
case "error":
prefix = "ERORR: "
break;
case "warning":
prefix = "WARNING: "
break;
}
win.document.getElementById(location).value =
win.document.getElementById(location).value + prefix + m + "\n";
win.focus();
} else if (initialized&&!ready) {
// Now it is time to create the timer...
var timer = Components.classes["#mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
// ... and to initialize it, we want to call
event.notify() ...
// ... one time after exactly ten second.
timer.initWithCallback(
{ notify: function() { log(m); } },
10,
Components.interfaces.nsITimer.TYPE_ONE_SHOT
);
} else {
init();
log(m);
}
}
var log = function(m, level) {
_log(m, level, 'debug');
}
var poly = function(m, level) {
_log(m, "empty", 'polyml');
}
var close = function() {
win.close();
}
var setReady = function() {
ready = true;
}
var init = function() {
initialized = true;
var ww = Components.classes["#mozilla.org/embedcomp/window-
watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
win = ww.openWindow(null, "chrome://polymlext/content/
console.xul",
"console", "chrome,centerscreen,
resizable=no", null);
win.onload = setReady;
return win;
}
return {
init: init,
log : log,
poly : poly,
}
}());
// turning Console Class into an XPCOM component
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function Console() {
this.wrappedJSObject = this;
}
prototype2 = {
classDescription: "A special Console for PolyML extension",
classID: Components.ID("{483aecbc-42e7-456e-b5b3-2197ea7e1fb4}"),
contractID: "#ed.ac.uk/poly/console;1",
QueryInterface: XPCOMUtils.generateQI(),
}
//add the required XPCOM glue into the Poly class
for (attr in prototype2) {
Console.prototype[attr] = prototype2[attr];
}
var components = [Console];
function NSGetModule(compMgr, fileSpec) {
return XPCOMUtils.generateModule(components);
}
I'm using this component like this:
console = Cc["#ed.ac.uk/poly/console;1"].getService().wrappedJSObject;
console.log("something");
And this breaks the sockets :-S =)
UPDATE #2
Ok, if anyone is interested in checking this thing out I would really
appreciate it + I think this is likely some kind of bug (Seg fault
from javascript shouldn't happen)
I've made a minimal version of the extension that causes the problem,
you can install it from here:
http://dl.dropbox.com/u/645579/segfault.xpi
The important part is chrome/content/main.js:
http://pastebin.com/zV0e73Na
The way my friend and me can reproduce the error is by launching the
firefox, then a new window should appear saying "Opened socket on
9999". Connect using "telnet localhost 9999" and send a few messages.
After 2-6 messages you get one of the following printed out in the
terminal where firefox was launched:
1 (most common)
Segmentation fault
2 (saw multiple times)
firefox-bin: Fatal IO error 11 (Resource temporarily unavailable) on
X
server :0.0.
3 (saw a couple of times)
GLib-ERROR **: /build/buildd/glib2.0-2.24.1/glib/gmem.c:137: failed
to
allocate 32 bytes
aborting...
Aborted
4 (saw once)
firefox-bin: ../../src/xcb_io.c:249: process_responses: Assertion
`(((long) (dpy->last_request_read) - (long) (dpy->request)) <= 0)'
failed.
Aborted
If you need any more info or could point me to where to post a bug
report :-/ I'll be glad to do that.
I know this is just one of the many bugs... but perhaps you have an
idea of what should I do differently to avoid this? I would like to
use that "console" of mine in such way.
I'll try doing it with buffer/flushing/try/catch as people are suggesting, but I wonder whether try/catch will catch the Seg fault...
This is a thread problem. The callback onInputStreamReady happened to be executed in a different thread and accessing UI / DOM is only allowed from the main thread.
Solution is really simple:
change
input.asyncWait(reader,0,0,null);
to
var tm = Cc["#mozilla.org/thread-manager;1"].getService();
input.asyncWait(reader,0,0,tm.mainThread);

Resources