console.log into devTools into Electron app and renderer process - electron

Why my console.log doesn't display into devTools in my very simple electron app ?
I console.log into js file loaded by renderer process electron.
If I console.log into main process electron I can view the result into command line with no problem
I can see that the js file is loaded by the renderer process into devTools > network part. But nothing console.log wrote into devTools > Console part.
index.js :
const {app, BrowserWindow} = require('electron')
let win
function createWindow () {
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
webSecurity: false
}
})
win.loadFile('index.html')
win.webContents.openDevTools()
console.log('main test')
win.on('closed', () => {
win = null
})
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win === null) {
createWindow()
}
})
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
index.html file :
<h1>MAIN PAGE</h1>
<script type="javascript" src="midi-test.js"></script>
<button type="button">TEST</button>
midi-test.js file :
var navigator = require('jzz')
console.log('test')
if (navigator.requestMIDIAccess){
console.log('OK')
}
else{
console.log('KO')
}
I don't want to use electron-log npm package for writing console.log into OS file.
I don't want to redirect console.log renderer process to main process command-line.
Lot of questions about this issue but nothing simple response find.

In the index.html file, replace :
<script type="javascript" src="midi-test.js"></script>
With :
<script type="text/javascript" src="midi-test.js"></script>
Or :
<script src="midi-test.js"></script>
In fact javascript only is wrong

Related

How do I display console log in electron app

I'm currently creating a JS Desktop App using Electron. I'm able to get everything functional how I want it, but I want to be able to update the users on certain tasks and also display errors in the app itself.
Is there any way to add a section (terminal if you will) or something similar inside the UI, so I can log things out to the user?
Providing application feedback to your user is as simple as having a statusUpdate function in your main process send
a message (via your preload.js script) to your render process. Within your render process, listen for a message on the
assigned channel and once received, update the content of your DOM element.
main.js (main process)
// Import required electron modules
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
// Import required Node modules
const nodePath = require('path');
// Prevent garbage collection
let window;
function createWindow() {
const window = new electronBrowserWindow({
x: 0,
y: 0,
width: 800,
height: 600,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: nodePath.join(__dirname, 'preload.js')
}
});
window.loadFile('index.html')
.then(() => { window.show(); });
return window;
}
electronApp.on('ready', () => {
window = createWindow();
statusTest();
});
electronApp.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
electronApp.quit();
}
});
electronApp.on('activate', () => {
if (electronBrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// ---
function statusTest() {
let counter = 1;
let message;
setInterval(() => {
statusUpdate(`Status message ${counter} from main process.`);
counter++;
}, 1000);
}
function statusUpdate(message) {
window.webContents.send('statusMessage', message);
}
preload.js (main process)
// Import the necessary Electron modules
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
// Exposed protected methods in the render process
contextBridge.exposeInMainWorld(
// Allowed 'ipcRenderer' methods
'ipcRenderer', {
// From main to render
statusMessage: (message) => {
ipcRenderer.on('statusMessage', message);
}
}
);
index.html (render process)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Electron Test</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"/>
</head>
<body>
<label for="status">Status: </label>
<textarea id="status" cols="40" rows="10" disabled></textarea>
</body>
<script>
let status = document.getElementById('status');
window.ipcRenderer.statusMessage((event, message) => {
status.value += message + '\n'; // Append message
status.scrollTop = status.scrollHeight; // Show last entry
});
</script>
</html>

sending value url from ipcRender to ipcMain

Hey i am making a project where i want to send data to ipc main
my index.js
const {app, BrowserWindow , ipcMain} = require('electron')
const ejse = require('ejs-electron')
app.on('ready', () => {
ipcMain.on("getUrl",(event,url)=>{
console.log(url);
})
mainWindow = new BrowserWindow({
autoHideMenuBar: true,
icon: __dirname + '/logo.ico',
webPreferences: {
devTools: false,
nodeIntegration:true,
webviewTag:true
}
})
mainWindow.loadURL('file://' + __dirname + '/files/index.ejs');
})
index.ejs contains a anchor tag with value as link
<button id="dw" style="display: none;"><a class="button" id="dwl" onclick="heal()" value="#">Download</a></button>
<script src=download.js></script>
download.js i am able to alert the link but ipcRender not working
const { ipcRenderer } = require("electron");
function heal(){
var url = document.getElementById("dwl").value;
alert(url);
ipcRenderer.send("getUrl",url);
}
i am not able to send url from ejs file to main index.js file alert is working in download.js but some error in sending data to main file console.log is not working
The use of contextBridge within your preload.js script safely exposes API's you approve for use in your render
scripts.
Whist understanding how all this works can be challenging at first, becoming familiar with the below content and the
following code should put you in good stead for a solid understanding of how you can wire up your application.
Context Isolation
contextBridge
Enabling Content Isolation for remote content
Inter-Process Communication
ipcMain
ipcRenderer
webContents - contents.send(channel, ...args)
Some people like to implement concrete functions within their preload.js script(s). In this example,
the preload.js script is only used to configure whitelisted channel names for use between the main process and render
process(es). This keeps your code seperated. IE: Separation of concerns.
Let's set the channel name getUrl within the ipc.render.send array.
preload.js (main process)
// Import the necessary Electron components.
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
// White-listed channels.
const ipc = {
'render': {
// From render to main.
'send': [
'getUrl' // Channel name
],
// From main to render.
'receive': [],
// From render to main and back again.
'sendReceive': []
}
};
// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
// Allowed 'ipcRenderer' methods.
'ipcRender', {
// From render to main.
send: (channel, args) => {
let validChannels = ipc.render.send;
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, args);
}
},
// From main to render.
receive: (channel, listener) => {
let validChannels = ipc.render.receive;
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`.
ipcRenderer.on(channel, (event, ...args) => listener(...args));
}
},
// From render to main and back again.
invoke: (channel, args) => {
let validChannels = ipc.render.sendReceive;
if (validChannels.includes(channel)) {
return ipcRenderer.invoke(channel, args);
}
}
}
);
Let's set the webPreferences.contextIsolation value to true and specify the webPreferences.preload path.
webPreferences.nodeIntegration can be set to false, but in doing so webPreferences.contextIsolation should be
set to true to "truly enforce strong isolation and prevent the use of Node primitives".
Lastly, let's listen for a message from the render process on the getUrl channel.
main.js (main process)
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;
const nodePath = require("path");
// Prevent garbage collection
let window;
function createWindow() {
const window = new electronBrowserWindow({
x: 0,
y: 0,
width: 800,
height: 600,
show: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: true,
preload: nodePath.join(__dirname, 'preload.js')
}
});
window.loadFile('index.html')
.then(() => { window.show(); });
return window;
}
electronApp.on('ready', () => {
window = createWindow();
});
electronApp.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
electronApp.quit();
}
});
electronApp.on('activate', () => {
if (electronBrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// Listen for a message on the 'getUrl' channel
electronIpcMain.on('getUrl', (event, url) => {
console.log(url);
})
This file is fairly standard and easy to understand. Just adapt code for use with .ejs
Added Javascript code in between <script> tags for sake of brevity.
index.html (render process)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Electron Test</title>
</head>
<body>
<input type="button" id="dwl" value="#">
</body>
<script>
let button = document.getElementById('dwl');
button.addEventListener('click', () => {
// Send URL on the 'getUrl' channel
window.ipcRender.send('getUrl', button.value);
});
</script>
</html>

Button click event binding in playwright function in a new window electron js

I am new to electron and other front-end technologies. I am trying to implement a desktop app using electron. In this app on clicking a button "Run Playwright" a new window should open and run the playwright function in this new window!
I used below HTML code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Buyer-Assistant</title>
</head>
<body>
<h1>Hello World!</h1>
<button type="submit" id="btnEd" value="run playwright" >Run Playwright</button>
</body>
</html>
following the electron documentation!
main.js
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration:true,
contextIsolation: false,
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
electron preload!
preload.js
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type])
}
})
by clicking on the button call this function in a new window
playwright.js
const { _electron: electron } = require('playwright');
async function runPlaywright() {
// Launch Electron app.
const electronApp = await electron.launch({
args: ['main.js']
});
// Get the first window that the app opens, wait if necessary.
const window = await electronApp.firstWindow();
// Capture a screenshot.
await window.goto('http://whatsmyuseragent.org/');
await window.screenshot({ path: 'intro.png' });
// Exit app.
await electronApp.close();
};

Getting absolute file path from file input in isolated environment in Electron app

I am starting an Electron based desktop app, which extends existing web app capabilities.
I am interested whether I can get the absolute file path from file input. HTML is displayed inside a BrowserView, which has nodeIntegration disabled and contextIsolation enabled.
My simple test does return a valid file path in this case, though my understanding is that it shouldn’t.
Maybe I am missing something? That looks like a security vulnerability…
Can I count in my desktop app that Electron will return a valid file path in a scenario similar to the one in the code below?
main.js
const { app, BrowserWindow, BrowserView } = require('electron');
let mainWindow;
const createWindow = () => {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
});
let view = new BrowserView({
webPreferences: {
nodeIntegration: false,
contextIsolation: true
}
})
mainWindow.setBrowserView(view)
view.setBounds({ x: 0, y: 0, width: 800, height: 600 })
view.webContents.loadURL('http://localhost:8000/index.html')
mainWindow.on('closed', () => {
mainWindow = null;
});
};
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
}
});
index.html
<html>
<script type="text/javascript">
function _on_file_change_() {
file_input = document.getElementById('file1');
console.log(file_input.files[0]);
}
</script>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<input type="file" id='file1' onchange="_on_file_change_(this.files)"/>
</body>
</html>

Electron + Vue (SPA): Not allowed to load local resource: file:///app/src/Products.vue

I have an Electron app + Vue for rooting. I am having problems loading the content into a newly opened window. The window is launched from a Vue component. When it opens I get a blank window and:
Not allowed to load local resource: file:///app/src/Products.vue
I have tried different methods mentioned on stackoverflow but the error still persists.
<style scoped>
</style>
<template>
<div class="container-fluid">
Parent window...
<button type="submit" class="btn btn-primary" v-on:click="add">+ Add Product</button>
</div>
</template>
<script>
export default {
methods: {
add: function () {
const remote = require('electron').remote
const BrowserWindow = remote.BrowserWindow
let win
win = new BrowserWindow({
height: 600,
width: 800
})
win.loadURL(`file://${__dirname}/app/src/Products.vue`)
win.openDevTools()
}
}
}
</script>
In your case, child window must be created from the main process to launch a child window with local resources in Electron. You can use ipc (ipcMain, ipcRenderer) for this.
For example,
In main process :
function createChildWindow(payload) {
let child = new BrowserWindow({ parent :mainWindow
});
child.loadURL(url.format({
pathname: path.join(__dirname, 'child.html'),
protocol: 'file:',
slashes: true,
}));
child.once('ready-to-show', () => {
child.show()
});
}
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
createChildWindow(arg);
});
In renderer process(web page) :
const {ipcRenderer} = window.require('electron')
async launchChildWindow(){
ipcRenderer.send('asynchronous-message', '<payload>');
}
You can also write custom events like this,
// Renderer process
ipcRenderer.invoke('some-name', someArgument).then((result) => {
// ...
})
// Main process
ipcMain.handle('some-name', async (event, someArgument) => {
const result = await doSomeWork(someArgument)
return result
})

Resources