59

I've been looking around the web and on Stackoverflow but hadn't found an answer to this question. How would you execute a Powershell script from Node.js? The script is on the same server as the Node.js instance.

Matthew Crews
  • 4,105
  • 7
  • 33
  • 57

3 Answers3

91

You can just spawn a child process "powershell.exe" and listen to stdout for command output and stderr for errors:

var spawn = require("child_process").spawn,child;
child = spawn("powershell.exe",["c:\\temp\\helloworld.ps1"]);
child.stdout.on("data",function(data){
    console.log("Powershell Data: " + data);
});
child.stderr.on("data",function(data){
    console.log("Powershell Errors: " + data);
});
child.on("exit",function(){
    console.log("Powershell Script finished");
});
child.stdin.end(); //end input
muffel
  • 7,004
  • 8
  • 57
  • 98
  • Perfect. Thank you so much for the help. This is exactly what I was looking for. Worked flawlessly. – Matthew Crews Apr 16 '12 at 22:02
  • 4
    I know this is old but can the powershell be run with admin permissions? – Vandervidi Dec 03 '15 at 22:25
  • @Vandervidi have a look at the [node-windows](https://github.com/coreybutler/node-windows) npm package. It provides a function `elevate` which might be what you are looking for. – muffel Dec 14 '15 at 12:05
  • 1
    Is there are any way to pass a relative path to powershell script as second parameter? – Andrew Kostenko Oct 27 '16 at 08:50
  • 1
    How to pass arguments for the script file from nodejs – Ramyachinna Aug 01 '18 at 09:21
  • This is great in principle, but won't work with scripts with paths that have embedded spaces; it's generally better to invoke scripts via the `-File` parameter (and with the `-NoProfile` parameter for predictability), which also makes it easier to pass arguments: `child = spawn("powershell.exe", [ '-noprofile', '-file', "c:\\temp\\helloworld.ps1", "arg1", "arg2"])`. Without `-File`, `-Command` is implied (in Windows PowerShell, not in PowerShell Core). /cc @Ramyachinna – mklement0 Dec 04 '19 at 21:48
  • hi @muffel can we use nodejs child process to run dotnet commands?? – anirudh talluri Jul 26 '21 at 11:49
  • How it works in Linux: spawn("powershell.EXE" ? because it should be portable. Or we need to have different versions for Windows and Linux? – ZedZip Nov 09 '22 at 10:14
49

The newer way to do this

const { exec } = require('child_process');
exec('command here', {'shell':'powershell.exe'}, (error, stdout, stderr)=> {
    // do whatever with stdout
})
Honest Objections
  • 773
  • 1
  • 6
  • 13
  • 1
    Thanks! Solved with this solution! – writingdeveloper Feb 06 '21 at 11:36
  • How can you get this to work with an external powershell script? – Big Money Apr 17 '21 at 01:16
  • Read the script in as a string and replace 'command here' with the variable – Honest Objections Apr 18 '21 at 17:59
  • I looked up for child_process in npm repo and what I found in this link https://www.npmjs.com/package/child_process has this message under Read Me section: ** Security holding package - This package name is not currently in use, but was formerly occupied by another package. ** Also it has just 1 version and 7 years old. Just wanted to make sure I got the right one – Alwaysa Learner Apr 27 '23 at 16:59
  • 1
    @AlwaysaLearner child_process is a built in package. https://nodejs.org/docs/latest-v18.x/api/child_process.html – Johan Dahl Apr 27 '23 at 20:24
10

This option works for me, when the script is not already there, but you want to generate some commands dynamically, send them, and work with the results back on node.

var PSRunner = {
    send: function(commands) {
        var self = this;
        var results = [];
        var spawn = require("child_process").spawn;
        var child = spawn("powershell.exe", ["-Command", "-"]);

        child.stdout.on("data", function(data) {
            self.out.push(data.toString());
        });
        child.stderr.on("data", function(data) {
            self.err.push(data.toString());
        });

        commands.forEach(function(cmd){
            self.out = [];
            self.err = [];
            child.stdin.write(cmd+ '\n');
            results.push({command: cmd, output: self.out, errors: self.err});
        });
        child.stdin.end();
        return results;
    },
};

module.exports = PSRunner;
Javier Castro
  • 321
  • 3
  • 12
  • Will this not add all errors and output to the last executed command? I've asked some help [here](https://stackoverflow.com/questions/66778574/how-is-this-used-in-a-function-and-is-it-required?noredirect=1#comment118046903_66778574). – DarkLite1 Mar 24 '21 at 12:48