Search code examples
node.jspowershellcommand-line-interfaceexecutionpolicy

Execute PowerShell script from NodeJS results in "running scripts is disabled on this system"


I'm attempting to run a powershell script from node. Here is my current code:

try {
    var spawn = require("child_process").spawn,child;
    child = spawn("powershell.exe", ['-file', "..\\build.ps1", "-devmode"])
    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
} catch (error) {
    console.error(error);
}

The code is based on this question. When I run it, I get the following error:

Powershell Errors: File C:\<path>\build.ps1 cannot be loaded because running scripts is disabled on this system. For more information,
see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
    + CategoryInfo          : SecurityError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnauthorizedAccess

I have tried setting the execution policy Set-ExecutionPolicy -ExecutionPolicy Undefined -Scope LocalMachine and I also tried just bypassing it when calling the script, like this:

child = spawn("powershell.exe", ['-ExecutionPolicy ByPass', '-file', "..\\build.ps1", "-devmode"])

This just resulted in The term '-ExecutionPolicy' is not recognized as the name of a cmdlet, function, script file, or operable program.

So how can I execute this script from node without execution policy errors?


Solution

  • When you're using the Windows PowerShell CLI (powershell.exe) with the -File parameter to directly invoke a .ps1 script file, using the -ExecutionPolicy CLI parameter is indeed the only effective way to override the script-file execution policy in effect ad hoc, for the given process only: -ExecutionPolicy Bypass is equivalent to calling
    Set-ExecutionPolicy Bypass -Scope Process -Force from inside a PowerShell session.

    However, to do so from a spawn call, each argument - irrespective of whether it represent a parameter name or value - must be passed as its own array element:

    spawn("powershell.exe", ['-ExecutionPolicy', 'ByPass', '-file', "..\\build.ps1", "-devmode"])
    

    As for what you tried:

    In your attempt, spawn of necessity encloses '-ExecutionPolicy Bypass' in "..." on the resulting command line (on Windows), given that it contains spaces.

    When powershell.exe parses the resulting command line, it does not recognize
    "-ExecutionPolicy Bypass" as an attempt to pass the -ExecutionPolicy parameter with a value; in fact, it doesn't recognize this argument as a CLI parameter at all, and therefore defaults to treating it as PowerShell source code - i.e. as if it had been passed to the default CLI parameter, -Command (-c).

    That is, in effect your attempt was tantamount to submitting -ExecutionPolicy Bypass ... as a command from inside a PowerShell session, which results in the error you saw.