Разрешить отображение консоли PowerShell в NodeJS - PullRequest
1 голос
/ 26 июня 2019

У меня есть клиент NodeJS (Electron), который выполняет следующий код:

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);
});

Который запускает файл, но по-прежнему не показывает консоль.

Ответ предпочтительно разрешит мне запускать файлы powershell, не присоединенные к клиенту NodeJS, а также покажет консоль 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 ]

1 голос
/ 11 июля 2019

В конце концов я обошел эту проблему, используя 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 голос
/ 15 июля 2019

shell:true и detached:true, где достаточно, чтобы открыть PowerShell.

Я сделал это простое демо для отдельного PowerShell окна:

  • root:
    • index.js (он же ваш основной js-файл)
    • powerShell.js (отдельное окно powershell)
    • showTime.ps1 (он же ваш файл)

В powerShell.js обнаружит, что я разделил аргументы, которые держат окно PS открытым под переменной defaultPowerShellArguments.

Совет : Я вижу много powershell в параметре команды spawn, я не могу этого подчеркнуть, добавьте расширение .exe также при работе под Windows, правильное значение - 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
0 голосов
/ 11 июля 2019

Я подозреваю, что вам нужно будет передать опцию shell, чтобы сообщить node, в какой оболочке будет выполняться команда. Это значение по умолчанию process.env.ComSpec в Windows, которое, если по какой-либо причине не установлено, будет по умолчанию cmd.exe.

Ссылка: https://nodejs.org/api/child_process.html#child_process_default_windows_shell:

Хотя Microsoft указывает, что% COMSPEC% должен содержать путь к «cmd.exe» в корневой среде, на дочерние процессы не всегда распространяется одно и то же требование. Таким образом, в функциях child_process, где может создаваться оболочка, «cmd.exe» используется в качестве запасного варианта, если process.env.ComSpec недоступен.

Поддержка оболочки PowerShell стала доступна через this commit .

Поскольку команда exec работает, я бы посоветовал начать с нее и попытаться отобразить окно. Попробуйте передать shell: 'PowerShell' в объекте параметров. windowsHide по умолчанию false для child_process.exec, но также не помешает передать его:

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

Вы также можете настроить его на spawn с похожими параметрами: { shell: 'PowerShell', windowsHide: false }

...