DengSihan
DengSihan

Reputation: 2997

Electron :how to close app via js in 2021?

I want to close the Electron App by js.

"electron": "^13.1.7"

I read those questions carefully:

But none of those work for me.


All the below tests are base on the offical electron-quick-start

  1. According to the answers in questions above, I got these code:

index.html

  <body>
    <button id="close-app">
        close
    </button>
    <script src="./renderer.js"></script>
  </body>

main.js

const {BrowserWindow, remote} = require('electron')
...
app.whenReady().then(() => {
  ...
  app.on('activate', function () {
    ...
    document.getElementById("close-app").addEventListener("click", function (e) {
      remote.getCurrentWindow().close()
    })
  })
})

There is just no any effects or errors.

There is just no any effects or errors.

It seems like the code have never been run, I added a console.log('run') above the addEventListener and there is nothing been print in the console.


  1. According to the document, I got these code:

(change nothing of the offical electron-quick-start but only preload.js and index.html)

index.html

as same as above

preload.js

const { app } = require('electron');
window.addEventListener('DOMContentLoaded', () => {
  document.getElementById("close-app").addEventListener("click", function (e) {
      app.quit();
  })
})

got Uncaught TypeError: Cannot read property 'quit' of undefined only Uncaught TypeError: Cannot read property 'quit' of undefined


So, how can I close the Electron App by js?

Thanks a lot for anyone help!

Upvotes: 1

Views: 3397

Answers (2)

DengSihan
DengSihan

Reputation: 2997

for those who are not using the offical template but a Vue3 webpack based electron.

you have to create the window first in an async function which will return the win created by BrowserWindow()

main.js

import { BrowserWindow, ipcMain } from 'electron'

async function createWindow() {
    // Create the browser window.
    const win = new BrowserWindow({
        transparent: true,
        frame: false,
        webPreferences: {
            nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
            enableRemoteModule: true
        }
    })

    if (process.env.WEBPACK_DEV_SERVER_URL) {
        await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
        if (!process.env.IS_TEST) win.webContents.openDevTools()
    }
    else {
        createProtocol('app')
        // Load the index.html when not in development
        win.loadURL('app://./index.html')
    }

    return win;
}

app.on('ready', async () => {
    createWindow()
        .then(win => {
            ipcMain.on('close-app', () => {
                win.hide();
            });
            ipcMain.on('min-app', () => {
                win.minimize();
            });
        });
});

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    </head>
    <body>

        <span role="control-panel">
            <button type="button"
                id="min-app" 
                aria-label="minimize your app">
                <i class="mdi mdi-window-minimize text-2xl"></i>
            </button>

            <button type="button"
                id="close-app"
                aria-label="close your app">
                <i class="mdi mdi-close text-2xl"></i>
            </button>
        </span>

        <script>
            // for close/min app
            const { ipcRenderer } = require('electron');
            document.getElementById('close-app').addEventListener('click', () => {
                ipcRenderer.send('close-app');
            });
            document.getElementById('min-app').addEventListener('click', () => {
                ipcRenderer.send('min-app');
            });
        </script>
    </body>
</html>

Upvotes: 2

aabuhijleh
aabuhijleh

Reputation: 2464

Electron has modules that only work in the main process like app and modules that only work in the renderer process like ipcRenderer and modules that are common and can run in both processes

I recommend reading this article from the Electron docs which explains the process model

Preload scripts contain code that executes in a renderer process before its web content begins loading. These scripts run within the renderer context, but are granted more privileges by having access to Node.js APIs.

Because the app module is a main process module, if you try to access it from the preload script (renderer process), app will be undefined

// in preload.js
const { app } = require('electron');

console.log(app); // undefined

Instead, you should use inter-process communication to tell the main process to quit

// in main.js
const { app, ipcMain } = require('electron');

ipcMain.handle('quit-app', () => {
  app.quit();
});

// in preload.js
const { ipcRenderer } = require('electron');

window.addEventListener('DOMContentLoaded', () => {
  document.getElementById('close-app').addEventListener('click', () => {
      ipcRenderer.invoke('quit-app');
  });
});

Upvotes: 9

Related Questions