允许 powershell 控制台在 NodeJS 中显示
Allow powershell console to show in NodeJS
我有一个 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);
});
哪个 运行 是文件,但仍然没有显示控制台。
答案最好允许我 运行 未附加到 NodeJS 客户端的 powershell 文件,并且还会在 运行ning 时显示 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();
我怀疑您需要传递 shell
选项来告诉 node
在哪个 shell 上执行命令。这默认为 Windows 上的 process.env.ComSpec
,如果出于某种原因未设置,则默认为 cmd.exe
。
参考:https://nodejs.org/api/child_process.html#child_process_default_windows_shell:
Although Microsoft specifies %COMSPEC% must contain the path to 'cmd.exe' in the root environment, child processes are not always subject to the same requirement. Thus, in child_process functions where a shell can be spawned, 'cmd.exe' is used as a fallback if process.env.ComSpec is unavailable.
PowerShell shell 支持已通过 this commit 提供。
由于 exec
命令有效,我建议从这里开始并尝试让 window 显示。尝试在选项对象中传递 shell: 'PowerShell'
。对于 child_process.exec
,windowsHide
默认为 false
,但传递它也可能无害:
exec('powershell -ExecutionPolicy Bypass -File ' + updater_path, { shell: 'PowerShell', windowsHide: false }, function callback(error, stdout, stderr){
console.log(error);
});
您也可以通过类似的选项使其与 spawn
一起使用:{ shell: 'PowerShell', windowsHide: false }
我最终通过使用 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
批处理文件中的循环本质上只是为了在不打开命令 window 的情况下自行关闭。我根据它是哪种更新来传递参数。
shell:true
和 detached:true
足以打开 PowerShell。
我已经为独立的 PowerShell window:
制作了这个简单的 demo
- 根:
- index.js(也就是您的主要 js 文件)
- powerShell.js(分离的 powershell window)
- showTime.ps1(又名您的文件)
在 powerShell.js
中会发现我将保持 PS Window 在 defaultPowerShellArguments
变量下打开的参数分开。
Advice: I see alot of powershell
at the spawn
command parameter, i cannot stress this enough, add the .exe
extension too when running under Windows, correct ispowershell.exe
. If you happen to use just powershell
and nodepad
will all of a sudden pop-up echoing your script, you will have a hard time trying to figure it out.
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
我有一个 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);
});
哪个 运行 是文件,但仍然没有显示控制台。
答案最好允许我 运行 未附加到 NodeJS 客户端的 powershell 文件,并且还会在 运行ning 时显示 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();
我怀疑您需要传递 shell
选项来告诉 node
在哪个 shell 上执行命令。这默认为 Windows 上的 process.env.ComSpec
,如果出于某种原因未设置,则默认为 cmd.exe
。
参考:https://nodejs.org/api/child_process.html#child_process_default_windows_shell:
Although Microsoft specifies %COMSPEC% must contain the path to 'cmd.exe' in the root environment, child processes are not always subject to the same requirement. Thus, in child_process functions where a shell can be spawned, 'cmd.exe' is used as a fallback if process.env.ComSpec is unavailable.
PowerShell shell 支持已通过 this commit 提供。
由于 exec
命令有效,我建议从这里开始并尝试让 window 显示。尝试在选项对象中传递 shell: 'PowerShell'
。对于 child_process.exec
,windowsHide
默认为 false
,但传递它也可能无害:
exec('powershell -ExecutionPolicy Bypass -File ' + updater_path, { shell: 'PowerShell', windowsHide: false }, function callback(error, stdout, stderr){
console.log(error);
});
您也可以通过类似的选项使其与 spawn
一起使用:{ shell: 'PowerShell', windowsHide: false }
我最终通过使用 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
批处理文件中的循环本质上只是为了在不打开命令 window 的情况下自行关闭。我根据它是哪种更新来传递参数。
shell:true
和 detached:true
足以打开 PowerShell。
我已经为独立的 PowerShell window:
制作了这个简单的 demo- 根:
- index.js(也就是您的主要 js 文件)
- powerShell.js(分离的 powershell window)
- showTime.ps1(又名您的文件)
在 powerShell.js
中会发现我将保持 PS Window 在 defaultPowerShellArguments
变量下打开的参数分开。
Advice: I see alot of
powershell
at thespawn
command parameter, i cannot stress this enough, add the.exe
extension too when running under Windows, correct ispowershell.exe
. If you happen to use justpowershell
andnodepad
will all of a sudden pop-up echoing your script, you will have a hard time trying to figure it out.
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