Uncaught TypeError: Cannot destructure property 'dialog' of 'require(...).remote' as it is undefined even thought enable remote modules set to true - javascript

I am trying to open a dialog box in my electron app but when I Try importing it in my app.js the error in the title shows up even thought 'enableRemoteModule' is set to true .
I am trying to open a dialog box in my electron app but when I Try importing it in my app.js the error in the title shows up even thought 'enableRemoteModule' is set to true .
app.js
const { dialog } = require("electron").remote;
const OpenBookBtn = document.getElementById("OpenBookBtn")
const viewerElement = document.getElementById('viewer')
const CloseBookBtn = document.getElementById("CloseBookBtn")
WebViewer({
path:'../public/lib',
},viewerElement).then(instance =>{
instance.setTheme("dark");
})
viewerElement.style.display = 'none'
OpenBookBtn.addEventListener('click',()=>{
const file = dialog.showOpenDialog();
viewerElement.style.display = "block"
})
CloseBookBtn.addEventListener('click',(event)=>{
viewerElement.style.display = 'none'
})
index.js
const { app, BrowserWindow } = require('electron');
const path = require('path');
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
}
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false,
},
width: 800,
height: 600,
});
// and load the index.html of the app.
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Open the DevTools.
mainWindow.webContents.openDevTools();
};
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.

First install the remote module using
> npm install #electron/remote
In the new versions of electron, you have to include remote as
const remote = require('#electron/remote');
const { dialog } = remote;
And in your index.js file add the following
const remoteMain = require('#electron/remote/main');
remoteMain.initialize();
Also, after creating the mainWindow object
remoteMain.enable(mainWindow.webContents)

Related

My Electron app after packaging doesn't launch

hello guys so basically after packaging my app with multiple packagers it still doesnt want to load the window when i open my .exe file :/
const PHPServer = require('php-server-manager');
const { app, Menu, shell, ipcMain } = require('electron');
const config = require('config')
const path = require('path')
const MainWindow = require('./MainWindow')
let mainWindow;
process.env.NODE_ENV = 'production'
shell.showItemInFolder('fullPath')
const isDev = process.env.NODE_ENV !== 'production' ? true : false
const server = new PHPServer({
php: "foundation/php/php.exe", // <==== ADDED
port: 8000,
directory: path.resolve(__dirname)+'/source',
stdio: 'inherit',
directives: {
display_errors: 1,
expose_php: 1
},
config: `${__dirname}foundation/php/php.ini`
});
function createWindow() {
server.run();
mainWindow = new MainWindow('http://'+server.host+':'+server.port+'/', isDev)
mainWindow.on('closed',function(){
mainWindow = null;
})
}
// Close App
ipcMain.on('close-me', (evt, arg) => {
app.quit()
})
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
// PHP SERVER QUIT
server.close();
app.quit();
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
//app.disableHardwareAcceleration()
app.commandLine.appendSwitch('force_high_performance_gpu')
app.allowRendererProcessReuse = true
this is my main.js and im using PHP in this electron project
also note that i use electron-forge for packaging
when i run npm start , the window show up perfectly but whenever i package my tool and then try to open the exe file it seems like nothing show up only a small icon of the app in the explorer bar , pretty weird since there is no error in my code ,
anyone has an answer ?

google chrome gpu error in electron build

I have an electron app that works fine in development. But when I build to linux-x64, and try to open the executable, the program crashes with the error:
[xxxx:ERROR:sandbox_linux.cc(377)] InitializeSandbox() called with multiple threads in process gpu-process.
According to this page, https://simpleit.rocks/linux/ubuntu/fixing-common-google-chrome-gpu-process-error-message-in-linux/ this is a common problem in chrome-linux, and can be solved with the command:
google-chrome --disable-gpu --disable-software-rasterizer
However, I don't know how/where to implement this inside electron.
In reality, my app is a react project, converted into an electron project by by adding the following file as the entry. This is the only electron related file in my project (meaning it was 100% webapp aside from this).
const electron = require('electron'),
app = electron.app,
BrowserWindow = electron.BrowserWindow;
const path = require('path'),
isDev = require('electron-is-dev');
let mainWindow;
const createWindow = () => {
mainWindow = new BrowserWindow({ width: 480, height: 320 })
const appUrl = isDev ? 'http://localhost:3000' :
`file://${path.join(__dirname, '../build/index.html')}`
mainWindow.loadURL(appUrl)
mainWindow.maximize()
mainWindow.setFullScreen(true)
mainWindow.on('closed', () => mainWindow = null)
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
// Follow OS convention on whether to quit app when
// all windows are closed.
if (process.platform !== 'darwin') { app.quit() }
})
app.on('activate', () => {
// If the app is still open, but no windows are open,
// create one when the app comes into focus.
if (mainWindow === null) { createWindow() }
})
app.commandLine.appendSwitch("disable-software-rasterizer");
app.commandLine.appendSwitch('disable-gpu');
This should do the trick.
Adding those to the commendLine to your electron app.
This bug that I read helped me:
https://github.com/electron/electron/issues/28164

Outsource functionality from main.js

I've started building an electron application from scratch. So far I can modify the mainWindow by inserting all the logic in main.js, but I'd like to keep the logic in separate files. Unfortunatly I fail to import them correctly, so help would be nice..
// main.js
const { app, BrowserWindow, Menu, dialog } = require('electron');
const fs = require('fs');
const { test } = require('./test'); // test module to be imported
let win;
function createWindow() {
win = new BrowserWindow({
icon: `file://${__dirname}/dist/text-editor/favicon.ico`,
webPreferences: {
nodeIntegration: true
}
});
win.maximize();
win.loadURL(`file://${__dirname}/dist/text-editor/index.html`);
win.webContents.openDevTools();
//menu bar
const template = getTemplate();
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
win.on('closed', function () {
win = null;
});
console.log(test.getName()); // throws error
}
// create window on electron init
app.on('ready', createWindow);
// quit when all windows are closed
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', function () {
if (win === null) {
createWindow();
}
});
function getTemplate() {...} // for example move this method to new file
// test.js
const getName = () => {
return "Tom";
};
module.exports.getName = getName;
Running this code with ng build --prod && electron . throws:
Cannot read property 'getName' of undefined.
Thanks in advance ;)
Please import your js as const test = require('./test') and then use test.getName() in your main js file. when calling const {test} is trying to import the test object in the at relevant file . You can read more about that from this answer

Electron - Close initial window but keep child open

I am coding an electron app which is supposed to load a splash screen, and then open a new window. Afterwards the splash screen should be closed.
However I am not able to do that. In my index.js, the startup script, I have the following code:
const { app, BrowserWindow } = require("electron");
app.on("ready", () => {
let win = new BrowserWindow({ /*...*/ });
win.loadURL(`file://${__dirname}/splash/splash.html`);
win.on("ready-to-show", () => { win.show(); });
win.on("closed", () => { app.quit(); });
});
In splash.html I load the splash.js by using
<script>require("./splash");</script>
And in splash.js I tried the following code:
const remote = require("electron").remote;
let tWin = remote.getCurrentWindow();
let next = function(){
let win = new remote.BrowserWindow({ /*...*/ });
win.loadURL(`file://${__dirname}/main/main.html`);
win.on("ready-to-show", () => { win.show(); });
win.on("closed", () => { app.quit(); });
tWin.close();
// I could just use win.hide(); here instead
// of tWin.close(); but that can't really be the right way.
};
The function next() gets called after a timeout. The problem is, if called, the main window shows up for a second but both, slpash and main close instantly.
I tried to fix that by commenting out
win.on("closed", () => { app.quit(); });
in my index.js. But that led to the following error:
Attempting to call a function in a renderer window that has been closed or released.
Uncaught Exception:
Error: Attempting to call a function in a renderer window that has been closed or released. Function provided here: splash.js:38:9.
at BrowserWindow.callIntoRenderer (/usr/lib/node_modules/electron-prebuilt/dist/resources/electron.asar/browser/rpc-server.js:199:19)
at emitOne (events.js:96:13)
at BrowserWindow.emit (events.js:188:7)
Does anyone have an idea on how to prevent the newly created window from closing?
I usually use a diferent approach. Here's how a use do it:
create global var reference for the main window and the splash window, if not it will be self closed by the garbage collector.
load 'splash' browserwindow
on 'show' event I call a function to load 'main' window
on main window 'dom-ready', I close 'splash' and show 'main'
Here's one example of my main.js electron code, feel free to ask:
'use strict';
//generic modules
const { app, BrowserWindow, Menu } = require('electron');
const path = require('path')
const url = require('url')
const config = require('./config'); // => 1: archivo de configuracion
const fileToLoad = config.files.current ? config.files.current : config.files.raw;
const jsonData = require(fileToLoad); // => 2: archivo de datos (json)
const pug = require('electron-pug')({ pretty: true }, jsonData); // => 3: pasamos datos ya tratados a plantillas pug/jade
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win, loading
app.mainWindow = win;
function initApp() {
showLoading(initPresentation)
}
function showLoading(callback) {
loading = new BrowserWindow({ show: false, frame: false })
loading.once('show', callback);
loading.loadURL(url.format({
pathname: path.join(__dirname, '/src/pages/loading.html'),
protocol: 'file:',
slashes: true
}))
loading.show();
}
function initPresentation() {
win = new BrowserWindow({
width: 1280,
height: 920,
show: false,
webPreferences: {
experimentalFeatures: true
}
})
win.webContents.once('dom-ready', () => {
console.log("main loaded!!")
win.setMenu(null);
win.show();
loading.hide();
loading.close();
})
// Emitted when the window is closed.
win.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
win = null
})
win.loadURL(url.format({
//pathname: path.join(__dirname, '/src/pages/home.pug'),
pathname: path.join(__dirname, '/lab/pug/index.pug'),
protocol: 'file:',
slashes: true
}))
win.webContents.openDevTools() // Open the DevTools.
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', initApp)
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (win === null) {
initApp()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.*/

How to use electron's app.getPath() to store data?

I want to store images on the users computer, so I figure it should be stored in users data folder, as described here.
app.getPath(name)
name. Returns String - A path to a special directory or file associated with name. On failure an Error is thrown. You can request the following paths by the name:
home User's home directory
appData Per-user application data directory, which by default points to:
%APPDATA% on Windows
$XDG_CONFIG_HOME or ~/.config on Linux
~/Library/Application Support on macOS
userData The directory for storing your app's configuration files, which by default it is the appData directory appended with your app's name.
...
This is what I think you're supposed to do:
const app = require('electron');
alert(app.getPath('userData'));
But I get "getPath is not a function". I am not sure where to put it. It does not work from my html file or the renderer file, and I'm not sure how to use it from the main file because that's not linked to the web page.
Since the remote method is being considered deprecated, as shown here, I'd suggest you do this:
const {app} = require('electron');
console.log(app.getPath('userData'));
remote is considered dangerous.
app.getPath will be always available in main process.
Here is how to do it in renderer process without using remote (electron 7+)
Basically you have to use invoke in renderer.
in main
ipcMain.handle('read-user-data', async (event, fileName) => {
const path = electron.app.getPath('userData');
const buf = await fs.promises.readFile(`${path}/${fileName}`));
return buf;
})
in renderer
ipcRenderer.invoke('read-user-data', 'fileName.txt').then(
result => doSomething()
);
Here is what I use when I need to switch between dev and release
const electron = require('electron');
export const userDataPath = (electron.app || electron.remote.app).getPath(
'userData'
);
Another way to prevent the error "getPath is not a function" is to make the code work both in the renderer process and the main process:
const electron = require('electron');
const configDir = (electron.app || electron.remote.app).getPath('userData');
console.log(configDir);
I had trouble with app.getPath('userData') to save/load config files, etc and ended up using OS specific env vars in the meantime:
const getAppBasePath = () => {
//dev
if (process.env.RUN_ENV === 'development') return './'
if (!process.platform || !['win32', 'darwin'].includes(process.platform)) {
console.error(`Unsupported OS: ${process.platform}`)
return './'
}
//prod
if (process.platform === 'darwin') {
console.log('Mac OS detected')
return `/Users/${process.env.USER}/Library/Application\ Support/${YOUR_APP_NAME}/`
} else if (process.platform === 'win32') {
console.log('Windows OS detected')
return `${process.env.LOCALAPPDATA}\\${YOUR_APP_NAME}\\`
}
}
if you wanna do it in renderer process
try this,it is work for me
// main.js
const electron = require('electron')
const electronRemote = process.type === 'browser' ? electron :
require('#electron/remote')
const { app, ipcMain, Menu, globalShortcut } = require('electron')
const BrowserWindow = electronRemote.BrowserWindow
const isDev= require('electron-is-dev')
const { initialize, enable } = require('#electron/remote/main')
initialize()
let mainWindow
app.on('ready', ()=>{
mainWindow = new BrowserWindow({
width: 1024,
height: 600,
minWidth:600,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false
}
})
enable(mainWindow.webContents)
})
render process
// render process
const { app } = window.require('#electron/remote')
const savedPath = app.getPath('userData')

Categories

Resources