-1

I'm new with Electron and Vue JS and i want to try to execute an .exe file just by clicking on a button but it doesn't work and i don't understand why. I'm using child_process from nodeJS, i have node 18. This is my code :

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <button @click="executerExe"> Execute </button>
  </div>
</template>

<script>
import { execFile } from 'child_process';

export default {
  methods: {
    executerExe() {
      const executablePath = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";
      execFile(executablePath, (error) => {
        if (error) {
          alert("Une erreur produite") ;
        } else {
          alert('Le fichier .exe a été exécuté avec succès !') ;
        }
      });
    },
  },
};
</script>

Actually, nothing happen with this code when i click on the button "Execute". I know the call is working because i created an alert at the beginning of the method and it works. But the execution of the .exe isn't working.

If you have any idea, I will be grateful =)

Wing
  • 8,438
  • 4
  • 37
  • 46
SaltyShot
  • 19
  • 3

1 Answers1

1

Problem

As you've mentioned Vue, I assume the code you have in the question is your app's frontend. Frontend code cannot access Node APIs. This is because they are run in a separate process. From Electron's documentation:

The render process

Each Electron app spawns a separate renderer process for each open BrowserWindow (and each web embed). [...] Moreover, this also means that the renderer has no direct access to require or other Node.js APIs.

The main reason for this is security. Exposing Node APIs to frontend code increases the risk of a successful attack, especially if remote code is executed.

Solution

Electron provides a way to expose functionality that require Node APIs through something called a preload script. Preload scripts are passed into the renderer process when you instantiate the BrowserWindow. They are then exposed to the renderer process via contextBridge.exposeInMainWorld.

In your case, you'll need to:

  1. Move your code inside executerExe into a preload script. An example:
// preload.js

function executerExe() {
  executablePath = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";
  execFile(executablePath, (error) => {
    if (error) {
      alert("Une erreur produite") ;
    } else {
      alert('Le fichier .exe a été exécuté avec succès !') ;
    }
  });
}
  1. Expose it, using contextBridge.exposeInMainWorld:
// preload.js

const { contextBridge } = require('electron');

contextBridge.exposeInMainWorld(
  "apiKey", // Replace with your own key name
  {
    executerExe,
  }
);
  1. Attach it to the BrowserWindow:
// main.js

const { BrowserWindow } = require('electron')
// ...
const win = new BrowserWindow({
  webPreferences: {
    preload: 'path/to/preload.js'
  }
})
// ...
  1. Then you can call it using window.apiKey.executerExe (replace "apiKey" with whatever you chose) in your frontend code.

Further reading

I'd highly recommend (re-)reading documentation:

Wing
  • 8,438
  • 4
  • 37
  • 46