Search code examples
node.jspowershellspawn

Allow powershell console to show in NodeJS


I've got a NodeJS (Electron) client which is running the following code:

child = spawn("powershell.exe",['-ExecutionPolicy', 'ByPass', '-File', require("path").resolve(__dirname, '../../../../updater.ps1')]);
child.on("exit",function(){
    require('electron').remote.getCurrentWindow().close();
});

The file that this opens is a powershell file which downloads and unpacks an update. If I run this file manually, I get the powershell console which shows me a progress bar for the download and the unpacking. However, running it from code like above does not show the console.

How can I make my code show the powershell console during it's runtime? I'm having a hard time formulating search terms to find an answer to this.

Things I've tried:

  • Adding '-NoExit' to my 2nd parameter array
  • Adding { windowsHide: false } parameter
  • Adding '-WindowStyle', 'Maximized' to 2nd parameter array

I've also tried switching to exec.

exec('powershell -ExecutionPolicy Bypass -File ' + updater_path, function callback(error, stdout, stderr){
    console.log(error);
});

Which runs the file but still doesn't show the console.

An answer will preferably allow me to run powershell files un-attached to the NodeJS client, and will also show the powershell console while running.

Here is my current code:

updater = spawn("powershell.exe",['-ExecutionPolicy', 'ByPass', '-File', remote.app.getAppPath() + '\\app\\files\\scripts\\' + data.type + '_updater.ps1'], { detached: true, stdio: 'ignore' });
updater.unref();

Which actually does nothing, it doesn't even seem like it runs the script at all.

I've tried the same thing using a batch file, it's never opened.

updater = spawn("cmd",[remote.app.getAppPath() + '\\app\\files\\scripts\\launch_updater.bat'], { detached: true, stdio: ['ignore', 'ignore', 'ignore'] });
updater.unref();

Solution

  • I eventually worked around this by using exec to call a batch file, and this batch file runs the powershell file.

    //call buffer .bat file, close main window after 3 seconds to make sure it runs before closing.
    exec('start ' +  remote.app.getAppPath() + '\\app\\files\\scripts\\launch_updater.bat ' + data.type);
    setTimeout(function() {
        require('electron').remote.getCurrentWindow().close();
    }, 3000);
    

    launch_updater.bat:

    @ECHO OFF
    set arg1=%~1
    start powershell.exe -executionpolicy bypass -File "%~dp0/%arg1%_updater.ps1"
    for /f "skip=3 tokens=2 delims= " %%a in ('tasklist /fi "imagename eq cmd.exe"') do (
        if "%%a" neq "%current_pid%" (
            TASKKILL /PID %%a /f >nul 2>nul
        )
    )
    exit /b
    

    The loop in the batch file is essentially just so it will close itself without leaving a command window open. I pass an argument based on what kind of update it is.