对于一些常用的程序或系统监控之类的程序,你可能希望在电脑开机后就能自动运行,Electron 可以很方便的实现开机自动运行,甚至是跨平台的开机自动运行。

开机自动启动

在 Windows 中,开机启动可以通过写注册表的方式实现,你可以自己写注册表,也可以直接使用 Electron 提供的自动启动 API 来操作。

大多数情况下可以使用 Electron 提供的 API 来设置自动启动,Electron 的 API 可以根据不同的系统来设置开机启动的方式,可以很方便的实现多平台自启动。

配置开机自动启动需要传递程序位置,所以需要打包后才能自启动,不能在开发模式自启动。

开机自启动可以在主进程配置,不需要在打包配置区域配置。

下面在主进程配置自启动:

const { app, BrowserWindow } = require('electron');
const path = require('path');

let mainWindow = null;

app.on('ready', async () => {
  // 创建窗口
  mainWindow = new BrowserWindow({
    width: 800,
    height: 500,
    webPreferences: {
      webSecurity: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js')
    }
  });

  // 加载html
  await mainWindow.loadFile(path.join(__dirname, 'assets', 'index.html'));

  // 程序是否打包
  if (app.isPackaged) {
    // 获取自动启动状态
    const settings = app.getLoginItemSettings();
    if (!settings.openAtLogin) {
      // 如果没有启用自动启动就设置开机自动启动
      app.setLoginItemSettings({
        openAtLogin: true,
        path: app.getPath('exe'),
        args: ['--auto']
      });
    }
  }

  // 如果是开机自动启动的程序就最小化窗口
  if (process.argv.includes('--auto')) {
    mainWindow.minimize();
  }

  // 窗口关闭
  mainWindow.on('close', () => {
    mainWindow = null;
  });
});

上面通过 app.isPackaged 来检测程序是否打包,如果打包就使用 app.getLoginItemSettings() 获取自启动的状态。

通过 getLoginItemSettings() 可以获取自启动配置,其中包含一个 openAtLogin 属性,如果 openAtLogintrue 就是自启动。

如果检测到没有启用自启动就使用 app.setLoginItemSettings 来设置自启动,app.setLoginItemSettings 可以传入一个配置对象,其中包括:

  • openAtLogin 自启动状态,可以设置为 truefalse
  • path 程序路径
  • args 启动参数(可选),可以传入一个数组,启动的时候可以获取这些参数

如果要取消自启动还是可以使用 app.setLoginItemSettings ,把传入对象的 openAtLogin 设置为 false 就可以取消自启动。

我这里在启动的时候还使用了 process.argv.includes 来判断 --auto 参数是否存在,如果存在就说明程序是开机自动启动的。如果是自动启动就使用 mainWindow.minimize() 来让程序最小化。

要查看自启动是否设置成功可以打开 任务管理器,选择 启动 标签页,如果设置成功的话可以看到程序名称,你也可以在这里启用或禁用一个程序的自启动。

在任务管理器查看开机自启动

上图中的 auto-start 就是 Electron 编写的自启动程序。

你也可以直接选择注销或重启来验证自启动。

配置系统托盘(可选)

一般开机自动启动的程序都会有一个托盘图标,自启动后可以直接最小化到系统托盘,在任务栏是看不到程序的,使用 Alt + TabWin + Tab 也无法切到程序。

下面实现自启动和设置系统托盘,如果是自启动就直接不显示窗口:

const { app, BrowserWindow, Tray, Menu } = require('electron');
const path = require('path');

let mainWindow = null;  // 保存主窗口
let tray = null;  // 存放系统托盘
// 启动时是否传入了 --auto 参数
const autoStart = process.argv.includes('--auto');

app.on('ready', async () => {
  // 创建窗口
  mainWindow = new BrowserWindow({
    width: 800,
    height: 500,
    show: !autoStart,
    webPreferences: {
      webSecurity: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js')
    }
  });

  // 创建系统托盘
  tray = new Tray(path.join(__dirname, 'assets', 'favicon.ico'));
  // 托盘菜单模板
  const menu = [
    {label: '退出', role: 'quit'}
  ];
  // 给系统托盘设置菜单
  tray.setContextMenu(Menu.buildFromTemplate(menu));
  // 给系统托盘设置气球提示
  tray.setToolTip('显示窗口');

  // 托盘图标点击
  tray.on('click', () => {
    // 如果窗口是隐藏状态就显示窗口
    if (mainWindow.isVisible()) return false;
    mainWindow.show();
  });

  // 加载html
  await mainWindow.loadFile(path.join(__dirname, 'assets', 'index.html'));

  // 程序是否打包
  if (app.isPackaged) {
    // 获取自动启动状态
    const settings = app.getLoginItemSettings();
    if (!settings.openAtLogin) {
      // 如果没有启用自动启动就设置开机自动启动
      app.setLoginItemSettings({
        openAtLogin: true,
        path: app.getPath('exe'),
        args: ['--auto']
      });
    }
  }

  // 窗口关闭
  mainWindow.on('close', () => {
    mainWindow = null;
  });
});

上面自启动的时候会传入一个 --auto 参数,程序启动的时候使用 process.argv.includes('--auto') 来检测 --auto 是否存在,如果存在就说明程序是自动启动的,在创建窗口的时候直接把 show 设置为 false ,窗口就不会显示,只会显示托盘图标,点击托盘图标使用主窗口的 show() 方法来显示窗口。

下面就是托盘图标和托盘菜单:

Electron托盘图标和托盘菜单

上图中蓝色圈出的就是自启动的 Electron 程序。