在 Electron 中生成一个子进程

Spawn a child process in Electron

我正在使用 Node v6.2.2 和 Electron v1.2.5。

我有一个基于 Electron 构建的小应用程序,现在我需要 fork 进程到 运行 另一个节点进程中的一些长 运行ning 任务但它似乎不起作用,当我查看 ChildProcess 对象时,我可以看到参数 spawnargs[0] 是用电子可执行文件而不是节点初始化的,所以我所做的是我已经尝试使用 spawn 代替,但据我所知它不起作用。

这是我用于 spawn 过程的代码(在文件 ./modules/tester.js 中存在 ):

const {spawn} = require('child_process');

var child = spawn("node", ["worker.js"], { stdio: ['inherit', 'inherit', 'inherit', 'ipc'] });

const self = {};

self.start = () => {
    console.log("start");
    child.send("ping");
};

这是我用于 worker.js 文件的代码:

process.on("message", (data) => {
    console.log(data);
    console.log("pong");
});

最后这就是我的消费方式。

const {app} = require("electron");

const tester = require("./modules/tester");

app.on("ready", () => {
    tester.start();
});

也许我做错了,但我不这么认为,因为当我使用 nodejs 时,它似乎工作得很好。

我已经尝试了很多示例,但其中 none 似乎有效,另一种可能性是我需要在 Electron 中做一些特殊的事情才能使其正常工作,但我不知道。

如果您使用 --asar 标志编译 Electron,based on the docs 那将是一个问题。

还有 this issue 你不能将 stdio 附加到父级的地方。所以假设有一个分离的标准输入输出不是一个交易破坏者,你可以尝试 { stdio: 'ignore' }.

终于解决了

我解决这个问题的方法正好相反,NodeJS 在生产机器上可用,所以我只写了一个 start.js 脚本,基本上生成一个子进程到 运行 Electron 和父进程 我正在 运行ning 这个漫长的 运行ning 任务,最后我使用 IPC 在两个进程之间进行通信。

另外,你可以在 electron 进程中 fork nodejs 文件:

let serverProc = require('child_process').fork(
  require.resolve('./server.js'),
  ['--key', 'value'], // pass to process.argv into child
  {
    // options
  }
)
serverProc.on('exit', (code, sig) => {
  // finishing
})
serverProc.on('error', (error) => {
  // error handling
})

如果此答案是可移植的 .exe,则它适合您的应用程序。我自己没有使用过可安装的,所以对此了解不多。

边开发边创建子进程真的很容易。最简单的是使用 Node 的 child_process 中的 fork()(尽管我们可以根据需要使用任何 spawn/exec/execFile... 等等)。

当我们将应用程序打包为包含打包文件的可执行文件时,困难的部分就来了 "app.asar"。

关键是,你明白"app.asar"是什么吗? "app.asar" 乍一看就像一个普通的捆绑文件,但它实际上是一个 虚拟目录,这意味着您可以像访问任何其他目录一样在其中遍历, 也许只需将其视为目录名称即可。如果您在电子代码的主进程下执行 __dirname,您会看到该位置为 '/path/to/app.asar'.

你怎么看"app.asar"里面的东西? - reference

fs.readdirSync('/path/to/app.asar')

回答

您需要 bundle/copy 文件(该文件将 运行 在一个单独的进程中,例如文件名是:"child.process.js")分别放入您的打包程序所在的文件夹中(例如: electron-builder) 正在创建 EXE。假设您将所有内容打包到 "dist" 文件夹下,那么此 dist 文件夹应该包含文件 child.process.js。现在这个 "dist" 文件夹本身将变成 "app.asar".

当您为 fork() 指定 child.process.js 的路径时,如果文件 "child.process.js" 直接位于 dist 中,请将其命名为:

fork(path.join(__dirname, 'child.process.js'))

如果它存在于子目录下,请给出适当的路径。

有趣的是,上面的代码在将其用作可移植 EXE 和开发时都有效(如果将所有主要进程文件捆绑到一个文件中。)



我花了 3 天时间才弄明白这个问题。在测试 EXE 时我是如何进行调试的?我使用 fs 写入文件,然后打开它们并读取它们的内容。当我打印 fs.readdirSync('/path/to/app.asar') 的输出时,我才意识到解决方案。有趣的是我有两个 dist 文件夹,我正在为本地开发 dist 打包我的子文件,但没有为我打包应用程序的 dist 打包。

希望这对某人有所帮助!