Inter-Process Communication in Electron application
Here are examples illustrating Inter-Process Communication (IPC) in your Electron/Angular application, using the ipcMain (main process) and ipcRenderer (renderer process) APIs. These examples assume you have a basic understanding of how to set up an Electron app with an Angular frontend. Remember to handle potential errors (e.g., the main process might not be ready when the renderer tries to send a message). Always use error handling with promises or try...catch. These examples should give you a better understanding of how to handle custom events and complex IPC communication within your Angular Electron application. These examples also include additional error handling and data validation, which are important security considerations for any application that interacts with the user or the operating system.
- Opening a File Dialog
- • Main Process (electron-main.ts or similar):
- • Renderer Process (Angular Service or Component):
- Getting Application Settings
- • Main Process:
- • Renderer Process:
- Showing a Notification
- • Main Process:
- • Renderer Process:
- Sending Data from Angular to Main Process
- • Main Process:
- • Renderer Process (Angular Component):
- Minimize/Maximize Window (Control from Renderer)
- • Main Process:
- • Renderer Process (Angular Component):
- Quitting the Application (from Renderer)
- • Main Process:
- • Renderer Process:
- Progress updates
- • Main Process:
- • Renderer Process:
- Custom Event Handling
- • Main Process:
- • Renderer Process:
1: import { app, BrowserWindow, ipcMain, dialog } from 'electron';
2:
3: ipcMain.on('open-file-dialog', (event, arg) => {
4: const result = dialog.showOpenDialogSync(null, {
5: properties: ['openFile'],
6: filters: [{ name: 'Text Files', extensions: ['txt'] }], //Example Filter
7: });
8: if (result.canceled) return; // User cancelled
9:
10: const filePath = result.filePaths[0];
11: event.reply('file-path-selected', filePath); // Reply to Renderer
12: });
1: import { Injectable } from '@angular/core';
2: import { ipcRenderer } from 'electron';
3:
4: @Injectable({ providedIn: 'root' })
5: export class FileService {
6: openFileDialog() {
7: return new Promise<string>((resolve, reject) => {
8: ipcRenderer.once('file-path-selected', (event, filePath) => resolve(filePath));
9: ipcRenderer.send('open-file-dialog');
10: });
11: }
12: }
1: import { app, ipcMain } from 'electron';
2: const Store = require('electron-store'); // Install electron-store: npm install electron-store
3:
4: const store = new Store();
5: ipcMain.on('get-app-settings', (event) => {
6: event.reply('app-settings', store.get('settings'));
7: });
1: import { Injectable } from '@angular/core';
2: import { ipcRenderer } from 'electron';
3:
4: @Injectable({ providedIn: 'root' })
5: export class SettingsService {
6: constructor() {
7: ipcRenderer.on('app-settings', (event, settings) => this.handleSettings(settings));
8: }
9:
10: getAppSettings() {
11: ipcRenderer.send('get-app-settings');
12: }
13:
14: private handleSettings(settings: any) {
15: // Do something with the settings
16: console.log('Settings received:', settings);
17: }
18: }
1: import { app, ipcMain, Notification } from 'electron';
2:
3: ipcMain.on('show-notification', (event, message) => {
4: const notification = new Notification({ title: 'My App', body: message });
5: notification.show();
6: });
1: import { Injectable } from '@angular/core';
2: import { ipcRenderer } from 'electron';
3:
4: @Injectable({ providedIn: 'root' })
5: export class NotificationService {
6: showNotification(message: string) {
7: ipcRenderer.send('show-notification', message);
8: }
9: }
1: import { app, ipcMain } from 'electron';
2: ipcMain.on('data-from-angular', (event, data) => {
3: console.log('Data from Angular:', data);
4: //Process data here
5: });
1: import { ipcRenderer } from 'electron';
2: // ... in your Angular Component
3: sendData() {
4: const data = { name: 'John Doe', age: 30 };
5: ipcRenderer.send('data-from-angular', data);
6: }
1: import { app, ipcMain, BrowserWindow } from 'electron';
2: let win: BrowserWindow | null = null;
3:
4: app.on('ready', () => {
5: win = new BrowserWindow({ ... });
6: // ...
7: ipcMain.on('minimize-window', () => {
8: if (win) win.minimize();
9: });
10: ipcMain.on('maximize-window', () => {
11: if (win) win.maximize();
12: });
13: });
1: import { ipcRenderer } from 'electron';
2: // ...
3: minimizeWindow() {
4: ipcRenderer.send('minimize-window');
5: }
6: maximizeWindow() {
7: ipcRenderer.send('maximize-window');
8: }
1: import { app, ipcMain } from 'electron';
2: ipcMain.on('quit-app', () => app.quit());
1: import { ipcRenderer } from 'electron';
2: quitApp() {
3: ipcRenderer.send('quit-app');
4: }
1: import { app, ipcMain } from 'electron';
2:
3: ipcMain.on('progress-update', (event, progress) => {
4: event.reply('progress-updated', progress);
5: });
6:
7: //Example of sending data. This can be done on a timer or when an async function completes
8: setTimeout(() => {
9: const progress = 25;
10: win.webContents.send('progress-update', progress); // Send progress to renderer
11: }, 1000);
1: import { Component } from '@angular/core';
2: import { ipcRenderer } from 'electron';
3:
4: @Component({
5: selector: 'app-root',
6: template: `...`,
7: })
8: export class AppComponent {
9: progress: number = 0;
10:
11: constructor() {
12: ipcRenderer.on('progress-updated', (event, progress) => {
13: this.progress = progress;
14: console.log('Progress updated:', progress);
15: });
16: }
17: }
1: import { app, ipcMain } from 'electron';
2:
3: ipcMain.on('custom-event', (event, data) => {
4: // Handle the custom event and the associated data
5: console.log('Custom event received:', data);
6: });
7: Ren
1: import { ipcRenderer } from 'electron';
2: const data = { message: 'Hello from Angular!' };
3: ipcRenderer.send('custom-event', data); // Send the custom event with data
Electron context:
AngularElectron context:
Front context:
|