Electron - restart app / refresh environment variables - environment-variables

I'm currently working on an Electron app which uses a third party software. At some point I'm checking if that software is installed on the user's computer (it has to be in PATH), and if it's not there I just run the installation. As I said, the installation will append a directory to the PATH variable. After this happens, I need to restart the app in order to have access to the updated variables.
I already tried to use relaunch, just as in the docs, but it doesn't refresh the variables:
app.relaunch()
app.exit(0)
If I restart the app manually, then everything works ok.
Does anyone have some ideas ? Thanks.

My solution just works for production:
In production, your application could not get your PC's environment variable. So, when you create mainWindow in main.js, you should read environment variables and pass it to process.env variable. After you relaunch the application, it will reload env again as you expected.
Library in use:
https://github.com/sindresorhus/shell-env
https://github.com/sindresorhus/shell-path
import shellEnv from 'shell-env';
import os from 'os';
import shellPath from 'shell-path';
const isDevelopment = process.env.NODE_ENV === 'development';
function createMainWindow() {
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
},
width: 800,
height: 1000,
});
// ...
if (!isDevelopment) {
// TODO: if we're running from the app package, we won't have access to env vars
// normally loaded in a shell, so work around with the shell-env module
// TODO: get current os shell
const { shell } = os.userInfo();
const decoratedEnv = shellEnv.sync(shell);
process.env = { ...process.env, ...decoratedEnv };
console.log('DEBUG process.env', process.env);
// TODO: If we're running from the app package, we won't have access to env variable or PATH
// TODO: So we need to add shell-path to resolve problem
shellPath.sync();
}
// ...
}
After relaunching the application, the environment variables will be updated.
app.relaunch()
app.exit(0)
Notice: Without check !isDevelopment, after relaunching, the application won't be displayed. I have no idea.

Related

how to use environment variables in nx monorepo libs, exporting to multiple Nextjs apps

I'd like to load some environment variables into functions within my libs, and then be able to re-export this to several different Nextjs applications. i.e.
Within libs/api
export const getDatabaseConnection = () => {
const host = process.env.DB_HOST
const username = process.env.DB_USERNAME
...
return newDatabaseConnection
}
Within apps/myNextJSApp:
import { getDatabaseConnection } from '#myProject/api'
...
const databaseConnection = getDatabaseConnection()
...
When I run nx run myNextJSApp:serve it's unable to pull the environment variables from the .env within the root directory, however if I run nx run api:test it's completely happy. I think I could pull the environment variables from each app individually, and then pass them as params into my library functions, but this seems kind of tedious, and I was hoping theres a blanket solution to this where I could build my library modules with the environment variables, and export them to my NextJS apps.
Environment variables don't suppose to share by multiple apps. And it's better that you don't do it either. Every app you're creating should have its environment file. And don't read the environment from your libs directly. You must load the environment variable in your app and pass it to the lib.
For example, pass the needed config to the libs function:
// libs/api
export const getDatabaseConnection = ({host, username}) => {
const host = host
const username = usename
...
return newDatabaseConnection
}
// apps/nextjs
import { getDatabaseConnection } from '#myProject/api'
...
const databaseConnection = getDatabaseConnection({
host: process.env.DB_HOST,
username: process.env.DB_USERNAME
})
This way, your code is more reusable and maintainable.
And as I said, don't ever share your environment variables between apps.

How to read config file in electronjs app

It's my first time using Electron JS and nodejs. I've built a small app that reads some records from a database and updates them. Everything is working fine. I have a config file with the database credentials but when I build a portable win app, I cannot figure out how to read the config file that I would like to place next to the exe. I would like to have easy access to the file, so I could run the same app on different databases.
Can anyone tell me if what I want is possible and how? I already tried to get the exe location but I couldn't. I also read a lot of topics here but nothing seems to solve my problem (I might be doing something wrong).
I'm using electron-builder to build my app.
Thanks in advance.
Edit #1
My Config file is
{
"user" :"X",
"password" :"X",
"server":"X",
"database":"X",
"options":
{
"trustedconnection": true,
"enableArithAbort" : true,
"trustServerCertificate": true
}
}
This is what I've and works when I run the project with npm start
const configRootPath = path.resolve(__dirname,'dbConfig.json');
dbConfig = JSON.parse(fs.readFileSync(configRootPath, { encoding: 'utf-8' }));
However, when I build it, the app is looking for the file in another location different from the one where the executable is.
Use of Electron's app.getPath(name) function will get you the path(s) you are after, irrespective of which OS (Operating System) you are using.
Unless your application writes your dbConfig.json file, it may be difficult for your user to understand exactly where they should place their database config file as each OS will run and store your application data in a different directory. You would need to be explicit to the user as to where to place their config file(s). Alternatively, your application could create the config file(s) on the user's behalf (automatically or through a html form) and save it to a location 'known' to the application.
A common place where application specific config files are stored is in the user's application data directory. With the application name automatically amended to the directory, it can be found as shown below.
const electronApp = require('electron').app;
let appUserDataPath = electronApp.getPath('userData');
console.log(appUserDataPath );
In your use case, the below would apply.
const electronApp = require('electron').app;
const nodeFs = require('fs');
const nodePath = require('path');
const configRootPath = nodePath.join(electronApp.getPath('userData'), 'dbConfig.json');
dbConfig = JSON.parse(nodeFs.readFileSync(configRootPath, 'utf-8'));
console.log(configRootPath);
console.log(dbConfig);
You can try electron-store to store config.
Electron doesn't have a built-in way to persist user preferences and other data. This module handles that for you, so you can focus on building your app. The data is saved in a JSON file named config.json in app.getPath('userData').

electron-forge: securely add appleId and password

I'm trying to package my electron app, using electron-forge. In order to make the app available on macs, I need to codesign the app, which requires passing info such as appleId and app-specific-password in the package.json file.
How can I pass this information securely? (ie, not available to people who download the app)
If environmental variables are the way to go, I'm hoping to understand where I set the environmental variables (in a separate file? In the start command?) and how I access them in the package.json itself.
I'd appreciate any help to sort this out.
Details of what I've considered:
-The electron forge codesign documentation does not mention how to actually provide osx required details in a secure way. It does mention that it uses electron-notarize (among others) under the hood, and electron-notarize's documentation says: "Never hard code your password into your packaging scripts, use an environment variable at a minimum", but doesn't provide detail on how to do that.
-This stack overflow answer provides helpful info in terms of setting up a separate forge.config.js file, and then says you should "load your environment variables using process.env.YOUR_VARIABLE_NAME". It doesn't provide more detail--loading the environmental variables for a packaged app is what I'm trying to figure out here.
--This stack overflow answer mentions setting them manually, but doesn't mention how. It also mentions using the dotenv package--but I'd be surprised there's a separate package required for this task that is fundamental to any mac electron app.
I store them in an .env file in my project directory as follows:
APPLEID=your_id
APPLEIDPASS=your_password
In package.json I have a section:
"build": {
"productName": "PRODUCT",
"appId": "your app id",
"copyright": "Copyright",
"directories": {
"output": "build"
},
"afterSign": "scripts/notarize.js",
The afterSign points to a script scripts/notarize.js that will pull out the APPLEID and APPLEIDPASS using dotenv:
require('dotenv').config()
const { notarize } = require('electron-notarize')
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context
if (electronPlatformName !== 'darwin') {
return
}
const appName = context.packager.appInfo.productFilename;
return await notarize({
appBundleId: 'your app id',
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLEID,
appleIdPassword: process.env.APPLEIDPASS
})
}
It's those 2 last lines with appleId and appleIdPassword that pull out the environment variables.
Never commit the .env file to, for example, github. To make sure: add .env to your .gitignore file. Also: the script/notarize.js app is not part of your app itself, this runs while you build your app.
I've been able to hear back from one of the maintainers of electron forge, who said the way to do it is:
Load the environmental variables in the build script itself. For example: $ VAR1=something VAR2=somethingelse npm run make.
Then, reference those variables as appropriate in the forge.config.js file that package.json refers to. Example reference syntax: process.env.VAR1

How set app version in ember electron app?

I need set app versio like 1.006
I use ember-electron
Here:
enter image description here
I generally follow semvar versioning in my ember electron applications and use the package.json version as my app version. You can maintain your version number in one place (package.json) and use it wherever needed in your app.
To access the version in package.json, add the following code to your config/enviroment.js file:
/* eslint-env node */
'use strict';
const pjson = require('../package.json');
module.exports = function (environment) {
// ENV variables, etc ...
APP: {
appVersion: pjson.version,
appAuthor: pjson.author
},
// remainder of environment.js ...
return ENV;
};
Using app/controllers/application.js:
import Controller from '#ember/controller';
import config from '../config/environment';
export default Controller.extend({
appVer: config.APP.appVersion
});
your can then use {{appVer}} wherever you want to display your version number.

Converting Web app into Desktop app with Electron

Hey i am web developer and i wanted to make app for desktop. I discovered program named Electron i downloaded it from this page: electron.atom.io
Next I created files that are needed for running this app:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html>
Then main.js:
const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')
// 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
function createWindow () {
// Create the browser window.
win = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
// Open the DevTools.
win.webContents.openDevTools()
// 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
})
}
// 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', () => {
// 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) {
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.
and package.json:
{
"name" : "Test-App",
"version" : "0.1.0",
"main" : "main.js"
}
Now when i type in CMD
Electron .
i get the error
'electron' is not recognized as an internal or external command,
operable program or batch file.
Is there any way to run this program from app installed without CMD or How can i fix this?
Welcome to stackoverflow!
The package you installed is a demo package that is meant to demonstrate the different features Electron offers to developers. It is not suitable for your needs right now.
What you need instead is, as devilfart and Vadim pointed out, a global installation of the Electron runtime. This can be achieved by starting a command line with administrative rights and entering the following command:
npm install -g electron
This will install the Electron runtime as a global package inside your base node_modules directory and enable the use of the electron command.

Resources