开机自启动怎么实现?三个平台分别怎么处理?
考察点
- setLoginItemSettings 的跨平台行为
- 静默启动、参数透传、各平台底层机制
参考答案
1. 统一入口:app.setLoginItemSettings
const { app } = require('electron');
// 开启开机自启
app.setLoginItemSettings({
openAtLogin: true,
openAsHidden: false, // macOS:是否以隐藏状态启动
args: ['--autostart'], // 启动参数,Windows 有效
});
// 查询当前状态
const { openAtLogin } = app.getLoginItemSettings();
2. 各平台底层机制
Windows
- 写入注册表
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run,键值为应用 exe 路径 + args - 只影响当前用户;要全用户需写
HKEY_LOCAL_MACHINE(需要管理员权限,一般不做) - Squirrel 时代的坑:快捷方式指向
Update.exe,自启路径要处理好版本目录变化;nsis 包则直接指向安装目录的 exe,相对稳定 - 更可靠的做法:安装时由 nsis 脚本写注册表(卸载时同步清理)
macOS
- 早期用 LSSharedFileList(Login Items),macOS 13+ 底层迁移到 SMAppService
openAsHidden: true表示登录后以隐藏方式启动(agent 常用)- macOS 13+ 用户可在"系统设置 → 登录项"中看到并管理,应用名/图标展示要正常
- 沙盒(MAS 上架)应用必须用 SMAppService + helper 的正规姿势
Linux
- 没有统一 API,Electron 不支持,需自己写
.desktop文件到~/.config/autostart/:
[Desktop Entry]
Type=Application
Name=MyAgent
Exec=/opt/myagent/myagent --autostart
X-GNOME-Autostart-enabled=true
3. Agent 静默启动模式
开机自启时不应该弹窗打扰用户,通过 args 区分启动来源:
// main.js
const isAutostart = process.argv.includes('--autostart');
app.whenReady().then(() => {
createTray();
if (!isAutostart) {
createWindow(); // 手动启动才开窗,自启只驻留托盘
}
});
4. 常见坑
- 开发环境测试:
setLoginItemSettings在开发模式指向的是 electron 可执行文件,测不出真实效果,必须打包后验证 - 应用更新后自启失效:安装路径变化(尤其 Squirrel 的 app-x.y.z 目录)导致注册表路径过期,更新后要重写一次
- macOS 签名变化:重新签名/公证后 Login Item 状态可能被重置,升级版本后要重新设置
- 企业管控环境:组策略可能禁用 Run 键自启,agent 需要备选方案(计划任务 / 服务)
面试话术
跨平台用 setLoginItemSettings 统一处理,Windows 走注册表 Run 键、macOS 走 Login Items(13+ 是 SMAppService)、Linux 手写 autostart desktop 文件。工程上的重点是:args 传标记区分自启与手动启动实现静默驻留,以及版本更新后重新校正自启路径。
常见追问
- 用户禁止自启如何感知?
getLoginItemSettings()查询,设置页同步展示。 - macOS 上怎么做到"登录时启动且 Dock 不显示"?
LSUIElement(Info.plist)设为 true 让应用默认无 Dock 图标,或运行时app.dock.hide()。