I am trying to write a Node app that, once deployed, will log to Windows Event Log.
I looked through available packages and was able to successfully use node-windows to write logs to the Windows Event Viewer when I ran the app using the command line. However, when I used pkg to turn the app into an .exe file and tried to run the .exe file, it was no longer logging to Windows Event Log.
As an example, I tried writing a basic app as follows:
const EventLogger = require('node-windows').EventLogger;
const log = new EventLogger('TestApp');
log.info('Test test test!', 1000)
If I run this app using the command line (e.g. node index.js), it logs to Windows Event Viewer. However, when I run pkg to convert the project into an executable file and try to run the executable file (both as an instance and using Windows Task Scheduler), it no longer logs out.
I have already checked to ensure that the .exe is running as administrator, so I don't think it is an issue with permissions. Anyone have any thoughts on why the .exe may not be logging out? Are there any other NPM packages/libraries that provide the ability to log to Windows Event Log?
Thank you in advance!
pkg packages js source files and other assets into an EXE, and exposes them within a node process using a virtual file system. This works fine for most things, but breaks if any of those assets need to be used outside of your process.
For most of its functionality, the node-windows module distributes a few executables of its own or uses Windows builtins. It exec()s those EXEs on your behalf.
For the helpers distributed by the module, the EXE must exist on the real filesystem in order to exec() it. It is highly likely that pkg breaks this; you'd need to distribute those EXEs and place them on disk yourself.
Event logging uses the builtin eventcreate, which should work, but maybe pkg is doing something weird with the virtual filesystem that breaks how child_process works.
At any rate, I strongly recommend against using node-windows for logging because it exec()s a new child process for every log call. This is highly inefficient on Windows: it has to spawn a shell (cmd.exe) and then run the helper (eventcreate.exe), and process creation on Windows is slow. Painfully slow.
If you start logging enough things, you'll soon bring your entire system to its knees with process bookkeeping.
Instead, use a native module that calls the ReportEvent API directly. windows-eventlog fits this bill.
You'll also want to consider pkg's notes regarding native modules.
Native addons (.node files) use is supported, but packaging .node files inside the executable is not resolved yet. You have to deploy native addons used by your project to the same directory as the executable.
Related
Before I give some background, I'd like to clarify that I'm not looking for how to simply spawn a new script under the Electron runtime as a renderer process, I'm trying to use a plain Node runtime.
So I'm aware Electron has some different flavor of a JS runtime under its hood similar to NW.js and I'm trying to get consistent performant results for my report.
Unfortunately, this seems to be much more difficult than I had imagined. I'm specifically testing the speed of the mailparser module although that's not necessarily important here.
I first ran it on the Electron app we're working with, which uses Electron Forge. I called the test script through IPC as that's what we intend to use, so it was called within the callback for ipcMain.handle. Here, the performance was really bad and it was taking 30-50 seconds for our test to complete.
I then ran a test script that just opens a blank HTML file in the same Electron Forge app, and runs the test script in the background. This was much better at 8-12 seconds.
Next, I set up a new directory with a test set, a plain Electron installation, and a mailparser installation. I did not electron-rebuild here, but mailparser does rely on node-iconv and so has native bindings.
I ran a test script with Electron just calling the same line of code. This did not use Electron Forge. The performance here was slightly better at 5-9 seconds.
I then ran another test script, this time just with plain old node, and the performance here was excellent at 1-3s.
So I have two questions here:
Why is the performance varying so much in the Electron tests? Although I used IPCMain, I used the new .handle which should be asynchronous and run in the context of Electron's node runtime, so it should have the same performance as running outside the callback. Moreover, the Electron Forge and plain Electron tests also differ by a couple of seconds which made no sense to me as I assumed Electron Forge would just wrap the Electron binary under the hood.
Seeking optimal and consistent results, I'm wondering how I can spin up a child process with the node runtime inside Electron. Doing this normally just starts a new renderer process which is running Electron's (slower) JS runtime. I'd like to avoid leaving Electron Forge but the only solution I can think of is to bundle precompiled binaries with the process running under the Node runtime built for each platform.
For question 1 it’s hard to know what the problem is without being able to replicate it in code. You might try posting an issue on the Github site for the Electron team re this. They are more likely to know the answer, but they ask for code as well.
Having said that, it isn’t that hard to spin up a child process that is just running node and frees you from Electron/Electron Forge overhead. The easiest is to use node’s fork command, but to tell it to use the main node executable rather than electron.exe. You can just hand it a script to run, so you don’t need to worry about precompiled binaries.
The code below (and here) running on the main process will run a script called server.js in the same folder:
const serverPath = path.join(__dirname, 'server.js');
const { fork } = require('child_process');
child = fork(serverPath, [],
{
execPath: "node",
stdio: ['pipe', 'pipe', 'pipe', 'ipc']
});
If you do that you get a child node.exe process with IPC enabled, rather than an electron.exe process. It can be made to communicate over IPC with the main Electron process. It can also use any npm modules installed from your usual package.json, because the script can be in the same folder as your other scripts. So if it works this is quite a clean solution.
I entertained myself this afternoon by writing some code that does this. I’ve put this on Github. It uses mailparser to parse a simple mail in the node.exe process in server.js.
This also packages correctly with Electron Forge as far as I can see, in terms of including the correct scripts. It won't package node itself, so that either needs to be installed on the target machine or I think you'll need to distribute node.exe.
By the way it isn’t entirely clear whether you’ve actually tried this approach and it’s one of those scenarios where it runs slowly. There is still some overhead, because we’re setting up IPC. If it does still run slowly in your use case then I think it’s possible to use node’s spawn command to create a completely standalone process.
I am currently getting my feet wet using Express. To start out, I used express-generator to scaffold a simple app.
While examining the project, I noticed that the npm start command is mapped to a binary (bin/www). Upon further inspection I noticed that this file actually contains code to be executed in Node, hence the #!/usr/bin/env node pragma. For anyone having a deeper understanding of Express/Node the answer may be obvious, but still I am wondering: Why didn't they simply use a .js file to bootstrap the framework. That file could then be run using node www.js, I imagine.
There are probably a few reasons why the script was made an executable
npm scripts can be mapped to execute local JS files in the project or executables on the system.
By mapping npm start to bin/www it is effectively the same as running ./bin/www on the command line with the important distinction that by running it via a npm start, it will also work cross platform (e.g. on systems that ignore the hashbang statement, like Windows), otherwise you would need to run it as node bin/www on those systems.
There's a binary ready to add to startup scripts.
I have implemented a nodejs server that serves incoming requests to use the bluetooth services of the local computer. I want the nodejs server to be packed as an windows executable file so that I can distribute it. People should be able to just install/run that .exe which will install any packages required (if any) and run the server. How to do this?. I saw and tried node-webkit etc., but they are UI-centric, that is it can pack a nodejs application that opens a html page. But I want my server javascript file to be executed, like the way it is done in command prompt : node file-name.js. How to do this?
I've a server running with nodejs and for execute this I use a .bat file.
Create a .bat file
Inside of the file put:
cd path/to/server/
node índex.js
I used JXCore for this task in the past. It basically creates one executable that includes everything.
Unfortunately active development of is halted.
Solution:
You can use nexe for that.
Create a single executable out of your node.js app
Motivation
Ability to run multiple applications with different node.js runtimes.
Distributable binaries without needing node / npm.
Starts faster.
Lockdown specific application versions, and easily rollback.
Faster deployments.
Now I make my protractor to work. Then I have another question: How to package the spec files and all the dependencies into one file, such as rpm or other format, so I can easily install it on another machine to run it? I searched the Internet and found some tools to package the javascript and CSS and images used in web page. But in my case, I only need to package the javascript I write to do the testing to one file.
I appreciate any suggestions.
The short answer is that's not possible.
When you run protractor on a fresh machine you need to have
an instance of selenium-webdriver server running (with all the browsers you want to test)
nodejs
But, assuming that the new computer you run protractor in has nodejs and selenium-webdriver is set up (i.e. either the local computer has it running, or you're testing over network like using saucelabs), then I guess you can zip up the file to send as one file.
I have moved an existing node.js + express project to VS because I prefer the IDE over JetBrains for now (used VS for years, only peeked into Webstorm).
I used NTVS new project->from existing sources and all files were imported successfully.
Afterwards, I opened the project settings of my project and set the node.exe arguments to bin\www, startup file for express.
When I press F5 (debug) I get the console.log messages I have put into the www and app.js files in the opening command prompt, and it looks like the server is running (cannot confirm, I want to debug if everything is working), but the VS debugger directly exits again, it also does not open any page in the browser I selected for debugging.
My node app actually is a REST webservice, so I want to test different URLs with different parameters.
Also, I cannot access the app on the port I specified, though when I directly start it from node.exe I can, even though the command prompt is still open.
(I have NTVS and WebEssentials installed - some operations take a long long time, but I attribute this to NTVS being still an early version.)
Question: how does the Visual Studio debugger stay connected to the node.js application so I can use breakpoints and use any browser then to connect and test different URLs? (Even a breakpoint put on the console.log that gets printed during startup is not being triggered.)
For everyone who asks receives, and the one who searches finds....
(and yes, I did spend a long time searching and trying before posting here..)
Kind of nice to debug node.js server with VS..
hope this helps someone
Edit: The arguments to node.exe can be hard to read in the image. It must be
--debug=<portno>
that is with two dashes (and not just one) to specify the debug port.
Not so much knowledge on expressjs but with a recent release of NTVS 1.0 Alpha, I did find it supports remote debugging which can be also used to debug nodejs app running locally - anyway haven't tried if it works with nodejs app + expressjs but it should.
I followed the step in this video https://youtu.be/-ir9ZB8lUg4 which is
Run your nodejs with node.exe RemoteDebug.js <your_javascript_file>.
RemoteDebug.js has come when you install NTVS.
In Visual Studio, select Debug > Attach to Process
Select Node.js remote debugging for Transport
Enter localhost:5859 for Qualifier
Click Attach
This will put Visual Studio in debugging mode which you can set a breakpoint, do step-in/step-out, very same experience when you use VS to debug .NET app.
Its pretty straight forward with NTVS, you can download required version for your windows from github here
Once you install NTVS, NodeJS project templates will be added
Now, Goto File->New project -> Basic NodeJS Express 3 application (it will be available in javascript project templates)
Now just goto debug and select Start Debugging, add breakpoints where ever required and you can start debugging