How to pass parameters from main process to render processes in Electron

烂漫一生 提交于 2020-07-06 09:15:12

问题


I have an Electron app that can open different windows.

On app launch the app open a set of window(s) (that load the same HTML and JS files) but with params to change each window displayed infos.

Example :

app.on('ready', async () => {
  ...
  // open window for stuff 1
  win1 = new BrowserWindow({
     width: 1024,
     height: 728
  });
  win1.loadURL(`file://${__dirname}/app/app.html?id=1`);

  // open window for stuff 2
  win2 = new BrowserWindow({
     width: 1024,
     height: 728
  });
  win2.loadURL(`file://${__dirname}/app/app.html?id=2`);

Obviously passing params in file:// path doesn't work. I can't find a clear solution in Electron documentation or elsewhere on Internet to condition my rendered window to a param.

I can probably use IPC communication after window ready but it seems a little bit too complicated until I just want pass a variable to my child view.

P.S. : to be totally honest my application is built with React/Redux and the param I want to pass to view is the redux store key to listen for this view.


回答1:


A few methods:

loadURL Query String

The query string method others have posted seems to work fine. It might even be the easiest.

additionalArguments

Electron's documentation says additionalArguments is:

Useful for passing small bits of data down to renderer process preload scripts.

Main

const win = new BrowserWindow({
  width: 800,
  height: 600,
  backgroundColor: '#000000'
  webPreferences: {
    additionalArguments: ["myvarvalue", "secondvarvalue", "--another=something"]
  }
});

Renderer

window.process.argv is going to look something like:

["--num-raster-threads=2",
"--enable-gpu-memory-buffer-compositor-resources",
"--enable-gpu-async-worker-context",
...
"--renderer-client-id=4",
"myvarvalue",
"secondvarvalue",
"--another=something"]

It will append an array of strings. You could do something window.process.argv.slice(-3) to grab the last items in the array.


IPC Main / Render

Like you said, it seems complicated for what you are trying to do, but maybe this helps:

Main

const { ipcMain } = require('electron');

var mainProcessVars = {
  somevar: "name",
  anothervar: 33
}

ipcMain.on('variable-request', function (event, arg) {
  event.sender.send('variable-reply', [mainProcessVars[arg[0]], mainProcessVars[arg[1]]]);
});

Renderer

const { ipcRenderer } = electron;

electron.ipcRenderer.send('variable-request', ['somevar', 'anothervar']);

ipcRenderer.on('variable-reply', function (event, args) {
  console.log(args[0]); // "name"
  console.log(args[1]); // 33
});

This way allows you to send data besides strings.




回答2:


According atom source code the query string method is a reliable way to do that very simply, especially when we only need to pass a unique string param:

// main process
win1.loadURL(`file://${__dirname}/app/app.html?id=${id}`);

// rendered process
console.log(global.location.search);

https://github.com/electron/electron/issues/6504




回答3:


Using query string along with win.loadFile(),

// main process or renderer process 1
data = {"age": 12, "healthy": true}

let win = new BrowserWindow({
        webPreferences: {
          nodeIntegration: true
        }
      });

win.loadFile("public/print.html", {query: {"data": JSON.stringify(data)}});
// renderer process 2
const querystring = require('querystring');
let query = querystring.parse(global.location.search);
let data = JSON.parse(query['?data'])



回答4:


We can inject Javascript code execution (on window did-finish-load event) and trigger react re-rendering with correct redux state portion. But it requires additional lifecycle step in rendered process.

Using hash or query in "local filepath" sounds a little bit weird but in my case it take sense since the hash describe the redux store branch to take in consideration in this window (file://which-code-to-load#which-content).

So even if i'm not totally at ease with this approach right now I'll take the second option.

It's a shame that the API doesn't provide any way to declare global vars from main process on window opening. I'll post a feature request.




回答5:


Unfortunately, it seems pretty complicated. You probably won't be able to add variables to .html you render in electron in a nice way.

Of course - you can use url but it slows down booting very much (vy seconds) or you can execute Javascript in BrowserWindo, which also slows boot down.

The only way is the IPC and leaving javascript .html agnostic to variables from main process. Very sad though..




回答6:


For example:

Process script

In your main script write:

global.varsForWindow = {
    platform: process.platform
};

Window script

Where you need it in a window script:

var varsFromMainScript = require('electron').remote.getGlobal('varsForWindow');
console.log(varsFromMainScript.platform);



回答7:


You can share data between main and renderer processor using global variable:

Main processor:

global.id = 1;

Renderer processor:

let id = remote.getGlobal('id');


来源:https://stackoverflow.com/questions/38335004/how-to-pass-parameters-from-main-process-to-render-processes-in-electron

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!