正如标题所述,我想知道如何将来自Python进程的消息间歇地发送到我的渲染器进程。我已经尝试了很多技术,但我似乎错过了我认为的要点。
首先,我的js文件,我在其中对预加载中注册的API进行API调用(下一个片段)。我发起调用并等待多条消息返回。
console.log('Start installation!');
window.mainAPI.startInstallation('hello');
window.addEventListener("message", (event) => {
console.log(event);
});
Preload. js/ IpcRenderer。它涉及最后一个“端点”或通道。
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('mainAPI', {
openConnection: (data) => ipcRenderer.invoke('openConnection', data).then((result) => {
window.postMessage(result)
}),
saveConfig: (data) => ipcRenderer.invoke('saveConfig', data).then((result) => {
window.postMessage(result)
}),
saveModuleSelection: (data) => ipcRenderer.invoke('saveModuleSelection', data).then((result) => {
window.postMessage(result)
}),
startInstallation: (data) => ipcRenderer.invoke('startInstallation', data).then((result) => {
window.postMessage(result)
})
});
Main.js(为清晰起见,粘贴了完整内容):
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
const { PythonShell } = require('python-shell')
const fs = require('fs');
function startPython(event, data) {
let pyshell = new PythonShell('install.py', {mode: 'text'});
pyshell.send(JSON.stringify(data));
pyshell.on('message', function(message) {
// HOW TO SEND MESSAGES TO EVENT LISTENER FROM HERE
console.log('Sending: ' + message);
event.sender.send('startInstallation', message); // doesnt work
});
pyshell.end(function(err, code, signal) {
var res = {
'error': []
};
if (err) {
res.error.push(err);
throw err;
}
res.code = code;
res.signal = signal;
console.log('The exit code was: ' + code);
console.log('The exit signal was: ' + signal);
console.log('finished');
return JSON.stringify(res)
});
}
function write_env_vars(filename, string) {
try {
fs.writeFileSync(`./backend/${filename}.env`, string, 'utf-8');
return true
} catch(e) {
console.log(e);
return false
}
}
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
const createWindow = () => {
const win = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
})
win.loadFile('inethi/front/index.html')
}
var credentials, config, modules;
app.whenReady().then(() => {
ipcMain.handle('openConnection', async (event, args) => {
await sleep(200);
// add call to test_server_connection.py here.
credentials = JSON.parse(args);
console.log(credentials);
return write_env_vars('credentials', `CRED_IP_ADDRESS=${credentials.ip}\nCRED_USERNAME=${credentials.username}\nCRED_PASSWORD=${credentials.password}`);
})
ipcMain.handle('saveConfig', async (event, args) => {
await sleep(200);
config = JSON.parse(args);
console.log(config);
return write_env_vars('config', `CONF_STORAGE_PATH=${config.storagepath}\nCONF_DOMAIN_NAME=${config.domainname}\nCONF_HTTPS=${config.https}\nCONF_MASTER_PASSWORD=${config.master}\n`);
})
ipcMain.handle('saveModuleSelection', async (event, args) => {
await sleep(200);
modules = JSON.parse(args);
console.log(modules);
return write_env_vars('modules', `MODS_DOCKER=${modules.docker}\nMODS_TRAEFIK=${modules.traefik}\nMODS_NGINX=${modules.nginx}\nMODS_KEYCLOAK=${modules.keycloak}\nMODS_NEXTCLOUD=${modules.nextcloud}\nMODS_JELLYFIN=${modules.jellyfin}\nMODS_WORDPRESS=${modules.wordpress}\nMODS_PEERTUBE=${modules.peertube}\nMODS_PAUM=${modules.paum}\nMODS_RADIUSDESK=${modules.radiusdesk}\n`);
})
ipcMain.handle('startInstallation', async (event, args) => {
console.log('Starting installation');
const data = {
'credentials': credentials,
'config': config,
'modules': modules
}
await sleep(3000);
const res = startPython(event, data);
console.log('Installation done');
console.log(res);
return true
})
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
所以问题是前三个端点或通道工作正常。我返回true,eventListener捕获消息。但是对于最后一个通道,'startInstallation'通道,它不工作,我怀疑这和(异步--从来没有真正理解过)python脚本。我的目标是1)发送间歇性的(打印)消息(在main.js文件的顶部)在pyshell.on(...)部分,并发送一个最终的消息,如果脚本运行成功。
任何帮助将不胜感激!
1条答案
按热度按时间idfiyjo81#
在ContextBridge中,似乎没有公开接收事件或处理
IPCRenderer
事件的方法。如果您在contextBridge代码中添加类似的内容
然后在你的客户端代码中,你应该能够像这样使用它:
然后在你的
startPythonMethod
中,你可以像这样触发它,将值直接发送到渲染器窗口:您可能需要重构为首先创建browserWindow,然后注册ipc处理程序。您将窗口作为arg传递给您拥有的startPython方法。