Get path of associated file when opened on double click Electron builder - node.js

Information:
OS: windows 10
Electron Version: Latest
Electron Builder Version: Latest
I am trying to make an app that edits .txt files. I want to get the path of the text file when it is opened with the application (i.e. the user chooses to open the .txt with my app). I have included the following in the build of my package.json:
"fileAssociations": [
{
"name": "Text Files",
"description": "Plain Text File",
"ext": [
"txt"
]
}
],
This makes the application open with the file however how do I get the path of the file that was used to open the app. I know I have to do something with a process.argv however I have no idea how to use this. I have tried the below with no success:
ipcMain.on('get-file-data', function(event) {
var data = null;
if (process.platform == 'win32' && process.argv.length >= 2) {
var openFilePath = process.argv[1];
console.log(data)
win.webContents.send('openFile', openFilePath)
}
});
How can I get the path of the file?

This is the log of the whole process. As we can see here, the second argv is the path of the input file path. So process.argv[1] will be enough to the file path. Not sure why you can't get a path.
Maybe this comes from your ipc event listener. Which means the get-file-data is not fired correctly.
As you can see in this below image,I'm showing this process variable in this browser console. Here is how I exposed process variable to the renderer. But this is just for debug! Recommend not doing this in your production.
preload.js
process.once("loaded", () => {
window.process = process;
});
main.js
mainWindow = new BrowserWindow({
width: 1024,
height: 728,
minWidth: 800,
minHeight: 750,
webPreferences: {
enableRemoteModule: true,
preload: path.join(__dirname, "preload.js"),
}
});
And you can use window.process or process on your renderer

I managed to get the path with the following:
const { remote } = require('electron');
console.log(remote.process.argv[1])
This returns the path of the file used to open the app!

Related

Pre-load a JS file in puppeteer

I have a javascript file which spoofs browser properties. how can I preload I before loading any website?
I used to work with nightmare JS. we are using this
command
node main.js data-spoof.js "$proxy"
inside main.js file
var args = process.argv.slice(2);
var proxystr = 'socks4://' + args[1].replace(/"/g, '');
webPreferences: {
preload: path.resolve(args[0]),
},
switches: {
'proxy-server': proxystr,
},
}
}
Can page.evaluateOnNewDocument(pageFunction[, ...args]) help?

Cordova Electron app, openFileDialog event

In my app I open a new window with an external web pagte. This page let users to choose a file. I need to intercept the openFileDialog opened.
Is there a way to do this?
Alternatively ss there a way to execute a script from the external page that runs some function on my electron app?
Thank you
Example:
// open an external page
const { remote } = require('electron');
const { BrowserWindow } = remote;
win = remote.getCurrentWindow();
newWin = new BrowserWindow(
{
parent: win,
modal: false,
show: false,
width: 1280,
height: 1024,
webPreferences: {
nodeIntegration: false,
plugins: true
}
}
);
newWin.loadURL(url);
//Page into newWin will open a file choose dialog and i need to know this is happened...
Did you tried electron dialog, below code snippet uses a same electron thread
const { dialog } = require('electron')
console.log(dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] }))
To exchange information between process you may look into
ipc-main AND webContents

Electron application exits immediately after starting

I had an Electron 5 environment running on Windows 7.
Electron 5 was installed in the local node_modules.
I was able to develop and run the application from VSCode.
I ran 'ncu' and opted to upgrade to Electron 7.
This upgraded the electron (from 5.0.0 to 7.1.3) and socket.io modules (from 2.1.0 to 2.3.0).
Now, when running 'electron .', my application starts but exits before the window is rendered.
This is because I set the BrowserWindow to show:false and expose it on the ready-to-show event, which is never sent.
I tried downgrading to Electron 5.0.12 but even after removing node_modules the behavior persisted.
I had a global instance of Electron 7 (7.0.0) but the application was using version 5 per a document.write(process.versions.electron) statement in my HTML.
Regardless, I upgraded the global Electron version to 7.1.3 to match.
I then copied the electron-quick-start file, modified with numerous debug statements. The file is:
// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
const path = require('path')
// 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 mainWindow
function createWindow () {
// Create the browser window.
console.log('READY:create...');
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
// and load the index.html of the app.
console.log('load index...');
mainWindow.loadFile('index-none.html')
// Open the DevTools.
console.log('load devtools...');
mainWindow.webContents.openDevTools()
console.log('set handler...');
// Emitted when the window is closed.
mainWindow.on('closed', function () {
console.log('MAINWIN: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.
mainWindow = null
})
console.log('created');
}
// 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.
app.on('window-all-closed', function () {
console.log('onWall-close...');
// 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', function () {
console.log('onActivate...');
// 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 (mainWindow === null) 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 require them here.
console.log('setting timer');
setTimeout(()=>{
console.log('timing out...');
}, 15000)
console.log('setting timer2');
setTimeout(()=>{
console.log('timing2 out...');
}, 200)
console.log('setting timer5');
setTimeout(()=>{
console.log('timing5 out...');
}, 500)
console.log('setting timer7');
setTimeout(()=>{
console.log('timing7 out...');
}, 700)
setTimeout(()=>{
console.log('timing10 out...');
}, 1000)
setTimeout(()=>{
console.log('timing12 out...');
}, 1200)
setTimeout(()=>{
console.log('timing15 out...');
}, 1500)
setTimeout(()=>{
console.log('timing17 out...');
}, 1700)
The HTML file is:
<html>
<head><title>title</title></head>
<body>
Hello world.
</body>
</html>
When I run either "electron eqs.js" or ".\node_modules.bin\electron.cmd eqs.js" I get this output:
setting timer
setting timer2
setting timer5
setting timer7
READY:create...
load index...
load devtools...
set handler...
created
timing2 out...
timing5 out...
timing7 out...
timing10 out...
timing12 out...
timing15 out...
(Sometimes timing15 doesn't get printed).
In this case I see the BrowserWindow get created, but it remains blank. The developer tools do not open. Commenting out the line opening the developer tools changes nothing.
This behavior happens with both:
C:\electron\electron-quick-start>.\node_modules.bin\electron.cmd -v
v5.0.12
C:\electron\electron-quick-start>electron -v
v7.1.3
I don't understand why the process is exiting while timers are active, so something somewhere must be calling app.exit() or similar. Besides "What is going on?", my obvious question is: how do I fix this?
I don't have an actual answer to this problem, but it was fixed when I upgraded to Electron 7.1.9 as I commented in the bug report https://github.com/electron/electron/issues/21544#issuecomment-577242668
During the upgrade some process took an unusually long time to complete but when it did my application ran successfully. I was also able to downgrade to a previous version of Electron and my application still ran, even when using a version that was failing earlier.
EDIT:
This problem resurfaced when an attempt to upgrade to Electron 8.2.2 failed because the application was running in a debugger. Unfortunately, no amount of version up/down-grades (up to 8.2.3) was able to recover the environment. Ultimately, disabling the sandboxing from my package.json launch script allowed me to proceed. This is the new command structure:
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Electron: Main",
"protocol": "inspector",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"runtimeArgs": [
"--remote-debugging-port=9223",
"--no-sandbox", <<<<<-- PASS THIS COMMAND OPTION
"."
],
"windows": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
}
},
[...]
]
For anyone stumbling across this: I had a similar problem.
Deleting the local files on Windows under %appdata%/YOUR_APP_NAME fixed Electron failing to launch properly for me.

Electron - "Cannot read property 'on' of undefined"; tried reinstalling,

I'm testing an electron app but I'm getting this pernicious error:
"TypeError: Cannot read property 'on' of undefined"
The research I've done pointed to either a botched module install, a syntax issue, or passing in an undefined variable to the app.on, and I suspect the issue may be Electron being pointed to incorrectly (now it's being pointed to the folder ending in electron\dist\electron.exe, which I've heard might not the right location), but I'm unsure.
Despite checking the require command, syntax, rechecking, uninstalling, and reinstalling node, I can't seem to make this darn error go away. What could be causing this?
const electron = require('electron');
const os = require('os');
const fs = require('fs');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
var Mousetrap = require('mousetrap');
const path = require('path');
const url = require('url');
const ipc = electron.ipcMain;
let mainWindow;
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
/* More code in this and sub functions*/
}))
}
})
const preferencesManager = require('./preferencesManager');
/******
Send data to database given constructor created in preferencesManager
******/
// First instantiate the class because we want to turn the class into an object to be able to use.
const store = new Store({ //create a new getting and setting logic
//We'll call our data file 'user-preferences'
configName: 'user-preferences',
defaults: {
//800 x 600 is the default size of our window
windowBounds: { width: 800, height: 600}
}
});
// When our app is ready, we'll create our BrowserWindow
app.on('ready',function(){
//Set up a listener for what I've done in keycapture (in the renderer process)
//???
ipc.on('invokeAction', function(event, args){
/* Do some action */
});
});
You are probably trying to run your application like a node app with:
$ node index.js
The electron file is a binary file, not a JavaScript file, when you require it an run with node there will be no object to call electron.app, so it parses for null and cannot have an property. As in the getting started documento of Electron.JS you must run the application like this:
Change your package.json script session adding start:
{
"scripts": {
"start": "electron ."
}
}
Now run:
$ npm start
The code you posted has an error, witch may be an edition error while coping and pasting but it should loose some parenthesis and curly brackets:
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
/* More code in this and sub functions*/
}))
}
The application should now run correctly. I tested you exact code, removing the libs I did not have and it loaded with no errors.

Electron - How to load a html file into the current window?

I was looking all around: docs, google, etc., on how to load a html file in the main window of an electron app, but I can't find a way.
Is it really this complicated or dead simple?
With what I have came up is ajax, thus works:
$("#main").load("./views/details.html");
Another method I have found is via remote:
const {BrowserWindow} = require('electron').remote
let win = new BrowserWindow({width: 800, height: 600})
win.loadURL('https://github.com')
But this opens always a new window, and I need to replace the existing page
If you want to load a new URL in an existing window you can do this in the renderer process:
const { remote } = require('electron')
remote.getCurrentWindow().loadURL('https://github.com')
Note that Electron restarts the renderer process when a new URL is loaded, so you'll probably see a flash when that happens. This is why it's usually best to use a single page application (SPA) architecture when building Electron apps.
I know this post is quite old but it's the most popular one on Google in terms of the question of loading new layouts for windows.
I had the same white flash issue because I'm not using any single page framework like React or Vue.js (I'm planning to in the future). So if you are not using too, you can create a function on the main process that hides or shows which window you want to show to make it look like one-page app.
You can get and set each windows' size and position to make the transition better:
function loadPage(page) {
if (page == "landing") {
landingWindow.setSize(uiWindow.getSize()[0],uiWindow.getSize()[1])
landingWindow.setPosition(uiWindow.getPosition()[0],uiWindow.getPosition()[1])
landingWindow.show()
uiWindow.hide()
} else if (page == "main") {
uiWindow.getSize(landingWindow.getSize()[0],landingWindow.getSize()[1])
uiWindow.setPosition(landingWindow.getPosition()[0],landingWindow.getPosition()[1])
uiWindow.show()
landingWindow.hide()
}
exports.loadPage = loadPage;
And you can expose this function to window with a preload script like this:
const electron = require('electron')
const remote = electron.remote
const mainProcess = remote.require('./main')
window.loadPage = mainProcess.loadPage;
Don't forget to initialize both windows on the main process:
function createWindow() {
// Create the browser window.
landingWindow = new BrowserWindow({
width: 1820,
height: 720,
/* fullscreen: true, */
webPreferences: {
nodeIntegration: false,
preload: path.resolve(path.join(__dirname, "preloads/preload.js"))
},
show: false,
backgroundColor: "#222831"
});
landingWindow.loadURL(
url.format({
pathname: path.join(__dirname, "src/landing.html"),
protocol: "file:",
slashes: true
})
);
uiWindow = new BrowserWindow({
width: 1820,
height: 720,
/* fullscreen: true, */
webPreferences: {
nodeIntegration: false,
preload: path.resolve(path.join(__dirname, "preloads/preload.js"))
},
show: false,
backgroundColor: "#222831"
});
uiWindow.loadURL(
url.format({
pathname: path.join(__dirname, "src/mainui.html"),
protocol: "file:",
slashes: true
})
);
// and load the index.html of the app.
// Open the DevTools.
landingWindow.webContents.openDevTools();
// Emitted when the window is closed.
landingWindow.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.
landingWindow = null;
});
landingWindow.once("ready-to-show", () => {
landingWindow.show();
});
}

Resources