How to call function from Nodejs running as windows service

1.2k Views Asked by At

I have created windows service from nodeJs application using node-windows package. Below is my code.

Main.js

var Service = require('node-windows').Service;

// Create a new service object
var svc = new Service({
  name:'SNMPCollector',
  description: 'SNMP collector',
  script: './app.js',
  nodeOptions: [
    '--harmony',
    '--max_old_space_size=4096'
  ]
  //, workingDirectory: '...'
});

// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
  svc.start();
});

svc.install();

/* svc.uninstall(); */

App.js

const { workerData, parentPort, isMainThread, Worker } = require('worker_threads')


var NodesList = ["xxxxxxx", "xxxxxxx"]

module.exports.run = function (Nodes) {
  if (isMainThread) {
    while (Nodes.length > 0) {

    // my logic

      })
    }
  }
}

Now when I run main.js, it creates a windows service and I can see the service running in services.msc

But, how can I call this run() method which is inside the running service, from any outside application? I couldn't find any solution for this, any help would be great.

2

There are 2 best solutions below

0
On

You might consider simply importing your run function where you need it and run it there, then there is no need for a windows service or main.js - this assumes that "any outside application" is a Node application.

In your other application you you do the folowing:

const app = require('<path to App.js>');
app.run(someNodes)

For broader usage or if you do need to run it as a service, you could be starting an express (or another webserver) in your App.js with an endpoint that invokes your run function. Then from anywhere else you'll need to make an http call to that endpoint.

App.js

const express = require('express')
const bodyParser = require('body-parser')
const { workerData, parentPort, isMainThread, Worker } = require('worker_threads')
const app = express()
const port = 3000

var NodesList = ["xxxxxxx", "xxxxxxx"]

const run = function (Nodes) {
  if (isMainThread) {
    while (Nodes.length > 0) {

    // my logic

      })
    }
  }
}

app.use(bodyParser.json())

app.post('/', (req, res) => res.send(run(req.body)))

app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))

(Based off of example for express - https://expressjs.com/en/starter/hello-world.html)

You'll need to install both express and body-parser: $ npm install --save express body-parser from the directory of App.js.

From your other applications you will need to call the endpoint http://localhost:3000 with a POST request and the Nodes as a JSON array.

0
On

You can expose it on a port like the other answer mentions, though you'll want to make sure you don't expose it more broadly depending on the environment you're running in. There's a good answer here on ensuring the port is locked down.

As an alternative to exposing it on a port you can simply call the function by running the command in any other application:

node -e 'require("/somePathToYourJS/app").run()'

One concern is that app.js will now run at whatever permissions the calling application has. Although that can be resolved by running runas prior. More details here. But an example is:

runas /user:domainname\username "node -e 'require(^"/somePathToYourJS/app^").run()'"