I've tried nearly every example for scripts I can find. Every sample opens the terminal for a split second. Even this closes as soon as input is entered. Is this normal?
var rl = require('readline');
var prompts = rl.createInterface(process.stdin, process.stdout);
prompts.question("How many servings of fruits and vegetables do you eat each day? ", function (servings) {
var message = '';
if (servings < 5) {
message = "Since you're only eating " + servings +
" right now, you might want to start eating " + (5 - servings) + " more.";
} else {
message = "Excellent, your diet is on the right track!";
}
console.log(message);
process.exit();
});
There are 2 options that control this in Tools/Options/Node.js Tools/General:
Wait for input when process exists abnormally
Wait for input when process exists normally
Taken from https://nodejstools.codeplex.com/discussions/565665
Related
I have a electron application that opens a external program (in my case Office), and has to wait for the program to be closed.
the code I wrote works great but sometimes the child_process.on('close') event is fired 10 or 20 seconds after the program has closed. The code is:
const cp = require("child_process");
child = cp.spawn(path/to/Office.exe + ' "' + path/to/myFile.pptx + '"', {shell: true});
child.on('close', function (code) {
//do something
});
Most of the time it reacts after 1 or 2 seconds which is fine, but sometimes it takes up to 20 seconds until I receive the close event. The program closes fast (according to the task manager), but node seems to wait for something.
I also tried child.on('exit'), calling the program with cp.exec()and using the options.stdio: ignore for spawn, as I thought maybe node is waiting for some stream from the child. But that made no difference.
Does anybody know a safe way to speed that process up?
I have tried your code and the close event triggers with a 0.5-2s delay, bearable i would say.
However, the 20s delay did not occur, but if this problem still persists on your end, you can try the approach below, which consists in checking the spawn pid.
const pidExists = (pid) => {
let pidOk = true;
try {
process.kill(pid, 0);
} catch (e) {
pidOk = false;
}
return pidOk;
};
const cp = require("child_process");
// I added the detach option because we won't need that process anymore since we're following the PID.
let child = cp.spawn(path/to/Office.exe + ' "' + path/to/myFile.pptx + '"', {shell: true, detach: true});
let officePID = child.pid; // this is the spawn pid
setInterval(()=>{
if( pidExists(officePID)){
console.log('file is still open', new Date().getTime());
}else{
console.log('file was closed', new Date().getTime());
process.exit(0);
}
}, 500);
This is a better approach since you said that the task manager shows you that the program was closed.
I was able to print raw ZPL commands from PHP directly to the printer, except that I can't print more than 1 label at once after windows update to windows-10 on the TLP 2844-Z printer and my first time when installing WebClientPrint Processor (WCPP) in windows-10. When I was trying to emulate ZPL printer in the ZPL Printer app it also happened. The only exception was when I try this on the mac Safari browser, it's doing fine.
Working request script (still working in Safari, and previously in all other browser):
for(var i=0; i<rows.length; i++){
javascript:jsWebClientPrint.print('useDefaultPrinter=' + $('#useDefaultPrinter').attr('checked') + '&printerName=' + $('#installedPrinterName').val() + '¶m=' + rows[i].value);
}
What's preventing me was the permission asking:
on Chrome weren't generated as many time as the request were (which aren't the problem on Safari).
Example when request were 2:
it only ask for permission once, resulting (only 1 label printed):
when it supposed to be (2 labels printed):
I was able to reproduce the above by using the following script:
for (var i = 0; i < rows.length; i++) {
var url = ('useDefaultPrinter=' + $('#useDefaultPrinter').attr('checked') + '&printerName=' + $('#installedPrinterName').val() + '¶m=' + rows[i].value);
window.open('webclientprint:' + domain + url);
}
Which aren't ideal since many tabs would be generated only to print, where previously you don't need any new tab to do the same.
Any idea how to solve this? So that it would print as many as the request ask?
What I did to solve this was to make each request on a separate tab and closed the tab once it's executed. To make it simple I make it into a separate function.
Request script changed into:
for (var i = 0; i < rows.length; i++) {
if (i > 0)
delayPrint(rows[i], i); // separate function
else
javascript: jsWebClientPrint.print('useDefaultPrinter=' + $('#useDefaultPrinter').attr('checked') + '&printerName=' + $('#installedPrinterName').val() + '¶m=' + rows[i].value);
}
separate function used for delaying request and to make each request on a separate tab and closed the tab once it's executed:
function delayPrint(data, interval) {
setTimeout(function() {
var wnd = window.open('webclientprint:' + domain + ('useDefaultPrinter=' + $('#useDefaultPrinter').attr('checked') + '&printerName=' + $('#installedPrinterName').val() + '¶m=' + rows[i].value));
setTimeout(function() {
wnd.close(); // close once it's done
}, 1000);
}, interval * 3000);
}
im Developing an Air app for android and ios and im using workers too preform a heavy task in background (two swfs),i want to have SharedObjects in the worker swf(the background worker) ,is this possible ? or the data will be lost?
Everything you need to write to the same SharedObject is to specify the same path for both like
mySO = SharedObject.getLocal("myObjectFile","/");
more info here http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7d80.html
Here is a short code to make you sure that data won't be lost, workers are actually doing the same stuff as multiple flash players ran simultaneously. Just run 2 or more swf and see the result:
import flash.net.SharedObject;
var iterations:int = 100
function witeToSo()
{
var mySO:SharedObject = SharedObject.getLocal("myObjectFile", "/");
if (iterations > 0)
{
if (!mySO.data.str) mySO.data.str = ""
mySO.data.str += int(Math.random() * 10);
iterations--;
}
txt.text = "str: " + mySO.data.str + " symbolsTotal:" + (mySO.data.str.length) + "\n";
setTimeout(witeToSo, Math.random()*100);
}
setTimeout(witeToSo, 2000);
Also you need to think of how to synchronise your threads in case you want to write the data in specific order
I have a set of scripts in PowerShell. I built a GUI with a .HTA, but I am migrating over to a NODE.js like approach.
I have a working script, but I had to make a modification to work around the lost functionality to get input from the command line. I used to have the CMD prompt window appear where I would see all output and, if there was a prompt (Read-Host), the user could interact with it. To work around that, I am now using [Microsoft.VisualBasic.Interaction]::InputBox() to get input from the user when needed.
I have had issues trying to use child.stdin.write(); because my PowerShell process just hangs. It will not respond to my input.
I have tried every answer I have found on the net, with no success. The script that is called in production is a long running process, depending on the task selected it will take from 20 min to 3 hours.
So, the issue is, I cannot get the child.spawned process to send the input, or maybe PowerShell does not accept input from stdin.
Thanks for your help in advance.
CODE:
HTML:
<button type="button" id="btn_ExecuteReport">Run Report</button>
<button type="button" id="btn_StopReport" >Stop Report</button>
<button type="button" id="btn_SendInput" >Send this...</button>
<h2>Results:</h2>
<p id="result_id">...</p>
<br/>
JS (using Electron v 0.31.0, io.js v 3.1.0, jQuery v 1.7.2):
$(document).ready(function () {
$("#btn_ExecuteReport").click(function (event) {
event.stopPropagation();
global.$ = $;
var remote = require('remote');
// to get some paths depending on OS
var app = remote.require('app');
//clipboard
var clipboard = require('clipboard');
var shell = require('shell');
// for choosing a folder
var dialog = remote.require('dialog');
var spawn = require('child_process').spawn;
sCmd = "powershell.exe ";
sCmdArg = '&' + "'" + __dirname + "/app.ps1' " ;
// omit parameters for the purpose of this example
// + "-ODir '" + sOutputDirectory
// + "' -WDir '" + sWorkingDirectory + "'"
// + " -Report " + sReport
// + " -pSendEmail " + sSendEmail
// + " -pSendEmailHTMLBody " + sSendEmailHTMLBody
// + " -pCreateReport " + sCreateReport
// + " -pCheckReport " + sCheckReport
// + " -pEmailAction " + sEmailAction
// ;
$("#result_id").html("<p><font color='magenta'>Command: </font>"
+ sCmdConcat + "</p>");
// try again with spawn and event handlers
var psSpawn = spawn(sCmd, [sCmdArg]);
// add a 'data' event listener for the spawn instance
psSpawn.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
// add an 'end' event listener to close the writeable stream
psSpawn.stdout.on('end', function(data) {
console.log('Done with psSpawn...' );
});
psSpawn.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
// when the spawn child process exits, check if there were any errors and close the writeable stream
psSpawn.on('exit', function(code) {
if (code != 0) {
console.log('[EXIT] Failed: ' + code);
}
//Collect result from PowerShell (via clipboard)
sResultData = clipboard.readText("Text");
});
psSpawn.on('close', function(code) {
if (code != 0) {
console.log('[ISSUE] code: ' + code);
}
console.log('[CLOSE]');
});
//sending the input with button #btn_sendInput
$("#btn_SendInput").click(function (event) {
psSpawn.stdin.setEncoding('utf8');
psSpawn.stdin.write('ok');
psSpawn.stdin.write('\n');
psSpawn.stdin.write(os.EOL);
//uncomment following line to end stdin on first button press
//psSpawn.stdin.end();
});
// killing process
$("#btn_StopReport").click(function (event) {
event.stopPropagation();
psSpawn.kill('SIGTERM');
console.log('killed ' + psSpawn.pid);
});
});
});
PowerShell:
#work around to lack of Read-Host functionality
Write-Host "waiting"
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$computer = [Microsoft.VisualBasic.Interaction]::InputBox("Enter a computer name", "Computer", "$env:computername")
#
Write-Host "[Done] waiting"
#workaround END works
Write-Host "Computer: [$computer]"
# START omit ----------------
#if we remove the following lines, all works but we lose the functionality to ask for input from the command line
Write-Host "Propmt for OK"
$ok = Read-Host
#
Write-Host "Prompt. Value of 'ok': [$ok]"
# END omit ----------------
#Copy new message to clipboard
"we want to see this maessage on the browser. $computer" | clip
#Exit script returning the appropriate value
[Environment]::Exit(0)
exit
My console output is:
stdout: waiting
stdout:
stdout: [Done] waiting
Computer: [COMPUTER_NAME]
Propmt for OK
The script hands no matter how many times I press Send this.... The console output is (after pressing the #buton_StopReport):
killed 2548
Done with psSpawn...
[EXIT] Failed: null
[ISSUE] code: null
[CLOSE]
So this is my task:
You must collect the complete content provided to you by each of the
URLs an d print it to the console (stdout). You don't need to print
out the length, just the data as a String; one line per URL. The catch
is that you must prin t them out in the same order as the URLs are
provided to you as command-line arguments.
And I'm doing it like this:
var http = require('http');
var dataStream = [];
var dataArr = [];
var count = 0;
/*
Function to print results
#dataArr - array
*/
function printResults(dataArr) {
for (var i = 0; i < process.argv.length - 2; i++)
console.log(dataArr[i]);
}
/*
Function to get data from http
#i - int
Getting command line arguments as parametrs.
*/
function httpGet(i) {
http.get(process.argv[2 + i], function(res) {
res.setEncoding('utf8');
res.on('data', function(data) {
dataStream.push(data);
});
res.on('end', function() {
dataArr[i] = (dataStream.join(""));
dataStream = [];
count++;
if (count == process.argv.length - 2) {
printResults(dataArr);
}
});
res.on('error', function(e) {
console.log("Got error: " + e.message);
});
});
}
for (var i = 0; i < process.argv.length - 2; i++) {
httpGet(i);
}
And for some reason sometimes it stores data in array as it supposed, but sometimes it breaks and outputs complete nonsense.
Some results examples:
When working:
$ learnyounode verify program.js
Your submission results compared to the expected:
────────────────────────────────────────────────────────────────────────────
────
1. ACTUAL: "Shazza got us some trackies when as stands out like dog's ba
lls. Grab us a show pony heaps he hasn't got a lurk. She'll be right rubbish
mate it'll be budgie smugglers. You little ripper bloke heaps we're going t
op end. He's got a massive bog standard also built like a freckle. "
1. EXPECTED: "Shazza got us some trackies when as stands out like dog's ba
lls. Grab us a show pony heaps he hasn't got a lurk. She'll be right rubbish
mate it'll be budgie smugglers. You little ripper bloke heaps we're going t
op end. He's got a massive bog standard also built like a freckle. "
2. ACTUAL: "As dry as a sook and as dry as a cleanskin. As cunning as a
metho where get a dog up ya parma. "
2. EXPECTED: "As dry as a sook and as dry as a cleanskin. As cunning as a
metho where get a dog up ya parma. "
3. ACTUAL: "Gutful of gyno how come a mokkies. It'll be clacker and buil
t like a holy dooley!. Get a dog up ya boozer heaps come a captain cook. "
3. EXPECTED: "Gutful of gyno how come a mokkies. It'll be clacker and buil
t like a holy dooley!. Get a dog up ya boozer heaps come a captain cook. "
4. ACTUAL: ""
4. EXPECTED: ""
And an example when it's not working:
$ learnyounode verify program.js
Your submission results compared to the expected:
────────────────────────────────────────────────────────────────────────────
────
1. ACTUAL: "of bogan with it'll be rort. He hasn't got a give it a burl
flamin you little ripper dinky-di. Watch out for the mate's rate to shazza g
ot us some swag. "
1. EXPECTED: "He's got a massive op shop to you little ripper corker. Gutf
ul of bogan with it'll be rort. He hasn't got a give it a burl flamin you li
ttle ripper dinky-di. Watch out for the mate's rate to shazza got us some sw
ag. "
2. ACTUAL: "You little ripper thongs when as stands out like ropeable. T
rent from punchy boardies bloody as cunning as a brisvegas. "
2. EXPECTED: "You little ripper thongs when as stands out like ropeable. T
rent from punchy boardies bloody as cunning as a brisvegas. "
3. ACTUAL: "As dry as a uluru when come a scratchy. Flat out like a ute
with get a dog up ya chrissie. As busy as a fair go no worries it'll be fair
dinkum. She'll be right freo when it'll be cracker. He's Watch got out a fo
r massive the op crook shop my to as you busy little as ripper a corker. bru
mby. Gutful "
3. EXPECTED: "As dry as a uluru when come a scratchy. Flat out like a ute
with get a dog up ya chrissie. As busy as a fair go no worries it'll be fair
dinkum. She'll be right freo when it'll be cracker. Watch out for the crook
my as busy as a brumby. "
4. ACTUAL: ""
4. EXPECTED: ""
Don't treat the data you receive on res.on("data") as an array. Instead, treat it as a string and define it as a variable within the http function (not as a global variable) and do str += data.
Alternatively, you could look at using a library like Async to manage the correct ordering of the async functions you need to execute, as you need each Async to be executed and returned in sequential order.
So the problem was:
Your code makes the assumption that the 3 http responses will not
overlap - that a data event for one response will never occur before
the end event of the previous response, this is not always the case. I
recommend you move the definition of your dataStream variable inside
your httpGet function, this way each request/response will have its
own variable and they cannot interfere with each other, regardless of
timing.
So I refactored my solution to look like this, and now it works 100% of the time:
var http = require('http');
var dataArr = [];
var count = 0;
/*
Function to print results
#dataArr - array
*/
function printResults(dataArr) {
for (var i = 0; i < process.argv.length - 2; i++) {
console.log(dataArr[i].replace('undefined', ''));
}
}
/*
Function to get data from http
#i - int
Getting command line arguments as parametrs.
*/
function httpGet(i) {
http.get(process.argv[2 + i], function(res) {
res.setEncoding('utf8');
res.on('data', function(data) {
dataArr[i] += data;
});
res.on('end', function() {
count++;
if (count == process.argv.length - 2) {
printResults(dataArr);
}
});
res.on('error', function(e) {
console.log("Got error: " + e.message);
});
});
}
for (var i = 0; i < process.argv.length - 2; i++) {
httpGet(i);
}
More info: https://github.com/nodeschool/discussions/issues/1270