允许Powershell控制台在NodeJS中显示

时间:2019-06-26 20:33:14

标签: node.js powershell spawn

我有一个运行以下代码的NodeJS(电子)客户端:

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

此打开的文件是一个powershell文件,该文件下载并解压缩更新。如果手动运行此文件,则会得到Powershell控制台,该控制台会显示下载和解压缩的进度条。但是,从上面的代码运行它不会显示控制台。

如何使我的代码在运行时显示Powershell控制台?我很难制定搜索条件来找到答案。

我尝试过的事情:

  • '-NoExit'添加到我的第二个参数数组中
  • 添加{ windowsHide: false }参数
  • '-WindowStyle', 'Maximized'添加到第二个参数数组

我还尝试过切换到exec

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

哪个文件可以运行,但仍不显示控制台。

一个答案最好可以让我运行未附加到NodeJS客户端的powershell文件,并且还可以在运行时显示powershell控制台。

这是我当前的代码:

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

实际上什么也没做,甚至似乎根本没有运行脚本。

我使用批处理文件尝试了相同的操作,但从未打开过。

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

3 个答案:

答案 0 :(得分:1)

我最终通过使用exec来调用批处理文件来解决此问题,并且该批处理文件运行了powershell文件。

//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

批处理文件中的循环本质上就是这样,它将自动关闭而不会打开命令窗口。我根据更新的类型来传递参数。

答案 1 :(得分:1)

shell:truedetached:true足以打开PowerShell。

我为一个独立的 PowerShell 窗口做了以下简单的 demo

  • 根:
    • index.js(又称您的主要js文件)
    • powerShell.js(独立的powershell窗口)
    • showTime.ps1(又名您的文件)

powerShell.js中,我发现在defaultPowerShellArguments变量下分隔了使PS窗口保持打开状态的参数。

  

建议:我在powershell命令参数中看到很多spawn,我对此压力还不够,在Windows下运行时也添加了.exe扩展名,正确的是powershell.exe。如果您碰巧只使用powershell,而nodepad会突然弹出显示您的脚本,那么您将很难找出答案。

index.js

const powerShell = require('./powerShell');

let seconds = 5;
let remaining = seconds;
let nd = new Date().getTime() + (seconds * 1000);

setInterval(() => {
    remaining -= 1
    let time = new Date();
    console.log('Your code running at:', time.toTimeString());

    if (remaining === 3) {
        console.log('Opening powershell...')
        powerShell([
            "-File",
            "./showTime.ps1"
        ]);
    }

    if (time.getTime() > nd) {
        console.log('Main script will exit.');
        process.exit(0);
    }
}, 1000);

powerShell.js

module.exports = (spawnArguments) => {
    if (typeof spawnArguments === "undefined" || !(spawnArguments instanceof Array)) {
        spawnArguments = [];
    }
    const {spawn} = require('child_process');
    let defaultPowerShellArguments = ["-ExecutionPolicy", "Bypass", "-NoExit",];
    let powershell = spawn('powershell.exe', [...defaultPowerShellArguments, ...spawnArguments], {
        shell: true,
        detached: true,
        // You can tell PowerShell to open straight to the file directory
        // Then you can use the relative path of your file.
        // cwd: 'ABSOLUTE_PATH_TO_A_VALID_FOLDER'
        // cwd: 'C:/'
    });
}

showTime.ps1

Get-Date -Format G

答案 2 :(得分:0)

我怀疑您需要传递shell选项来告诉node在哪个shell上执行命令。在Windows上默认为process.env.ComSpec,如果由于某种原因未设置,则默认为cmd.exe

参考:https://nodejs.org/api/child_process.html#child_process_default_windows_shell

  

尽管Microsoft指定%COMSPEC%在根环境中必须包含指向“ cmd.exe”的路径,但是子进程并不总是受到相同的要求。因此,在可以生成外壳程序的child_process函数中,如果process.env.ComSpec不可用,则将“ cmd.exe”用作备用。

PowerShell Shell支持已通过this commit提供。

由于exec命令正在运行,因此建议从此处开始并尝试显示窗口。尝试在选项对象中传递shell: 'PowerShell'windowsHide的{​​{1}}默认为false,但也可以通过它:

child_process.exec

您也可以通过类似的选项将exec('powershell -ExecutionPolicy Bypass -File ' + updater_path, { shell: 'PowerShell', windowsHide: false }, function callback(error, stdout, stderr){ console.log(error); }); spawn一起使用