Electron自动更新时主进程崩溃导致更新失败怎么办?

程序员淑瑶 阅读 57

我在用Electron的autoUpdater实现自动更新,按官方文档写了基本逻辑,但每次主进程崩溃时更新流程就中断了。

代码是这样写的:


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

autoUpdater.setFeedURL('https://update.myapp.com');
autoUpdater.on('update-downloaded', () => {
  autoUpdater.quitAndInstall();
});
autoUpdater.checkForUpdates();

测试时故意让主进程报错崩溃,发现根本没触发’update-downloaded’事件。难道必须保证主进程存活才能更新?有没有办法让更新进程独立运行?

我来解答 赞 13 收藏
二维码
手机扫码查看
2 条解答
Top丶玉研
说实话,Electron原生的autoUpdater确实有这个问题。主进程挂了,autoUpdater实例自然也没了,更新流程肯定断。你没法让更新进程完全独立,因为autoUpdater本身就是主进程的一部分。

但这个问题有解法,核心思路是:把更新状态持久化,下次启动时继续。

先说你代码的问题,太简单了,完全没有容错机制。建议改成这样:

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

const updateStateFile = path.join(app.getPath('userData'), 'update-state.json');

// 持久化更新状态
function saveUpdateState(state) {
fs.writeFileSync(updateStateFile, JSON.stringify(state));
}

// 读取更新状态
function getUpdateState() {
try {
return JSON.parse(fs.readFileSync(updateStateFile, 'utf8'));
} catch {
return null;
}
}

// 清除更新状态
function clearUpdateState() {
try {
fs.unlinkSync(updateStateFile);
} catch {}
}

// 启动时检查是否有待安装的更新
function checkPendingUpdate() {
const state = getUpdateState();
if (state && state.pending) {
// 上次已经下载好了,直接安装
autoUpdater.quitAndInstall();
return true;
}
return false;
}

// 初始化更新逻辑
function initUpdater() {
// 先检查是否有pending的更新
if (checkPendingUpdate()) return;

autoUpdater.setFeedURL('https://update.myapp.com');

autoUpdater.on('update-downloaded', () => {
// 标记有待安装的更新
saveUpdateState({ pending: true, time: Date.now() });
autoUpdater.quitAndInstall();
});

autoUpdater.on('error', (err) => {
console.error('更新出错:', err);
clearUpdateState();
});

autoUpdater.checkForUpdates();
}

app.whenReady().then(initUpdater);


另外,我更推荐用electron-updater代替原生autoUpdater,它是electron-builder生态的一部分,功能完善很多。它支持增量更新、支持更多平台特性,而且内部已经帮你处理了很多边界情况。

const { autoUpdater } = require('electron-updater');

autoUpdater.autoDownload = false;
autoUpdater.autoInstallOnAppQuit = true; // 退出时自动安装

app.whenReady().then(async () => {
try {
const result = await autoUpdater.checkForUpdates();
if (result.updateInfo.version !== app.getVersion()) {
await autoUpdater.downloadUpdate();
autoUpdater.quitAndInstall();
}
} catch (err) {
console.error('更新失败,下次启动再试:', err);
}
});


还有个坑要注意,Windows上用Squirrel框架时,更新完成后会有个临时文件,electron-updater会自动处理这些,原生autoUpdater你得自己管。

最后说一句,主进程频繁崩溃本身就是个大问题,建议加上crashReporter收集崩溃日志,把根本原因找出来修掉。更新机制再健壮,也扛不住应用本身不稳定。
点赞 1
2026-03-01 17:10
司徒子武
这个问题的关键是Electron的autoUpdater本质上依赖主进程来完成更新流程,但其实我们可以通过一些技巧让更新过程更健壮。具体来说,解决思路是从架构层面将更新逻辑和主进程解耦。

首先需要明确的是,当主进程崩溃时确实会导致所有事件监听中断,这是Node.js单线程模型决定的。所以我们要做的是在主进程挂掉之前确保更新包已经下载并准备好安装。

这里推荐一个更可靠的方案:使用独立的更新器进程。这个方案的核心思想是创建一个专门负责更新的小型Electron应用,它的唯一职责就是处理更新相关的事情。下面是具体实现步骤:

第一步,创建一个单独的更新器项目,结构可以很简单:
updater/
main.js
package.json


第二步,在这个独立的更新器里写核心逻辑:
const { app, autoUpdater } = require('electron');

let updateFeed = 'https://update.myapp.com';
let isUpdating = false;

// 设置更新服务器地址
autoUpdater.setFeedURL(updateFeed);

// 监听错误事件
autoUpdater.on('error', (err) => {
console.error('更新出错:', err);
app.quit();
});

// 当检测到更新时触发
autoUpdater.on('update-downloaded', () => {
if (!isUpdating) {
isUpdating = true;
// 延迟安装更新,给主应用退出的时间
setTimeout(() => {
autoUpdater.quitAndInstall(false, true);
}, 5000);
}
});

// 开始检查更新
autoUpdater.checkForUpdates();

// 防止重复启动多个更新进程
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
} else {
app.on('second-instance', () => {
// 如果已经是运行状态,直接退出
app.quit();
});
}


第三步,在你的主应用中修改更新逻辑:
const { spawn } = require('child_process');
const path = require('path');

function checkForUpdates() {
// 启动独立的更新器进程
const updaterPath = path.resolve(process.resourcesPath, '..', 'updater', 'main.js');
const updaterProcess = spawn(process.execPath, [updaterPath], {
detached: true,
stdio: 'ignore'
});

// 让子进程独立运行
updaterProcess.unref();
}

// 在合适的地方调用checkForUpdates()
app.on('ready', () => {
checkForUpdates();
});


为什么要这样做?因为即使主进程崩溃了,这个独立的更新器仍然会继续运行。它会在后台默默地检查更新、下载更新包,并在适当的时候执行安装。通常我们会设置一个延迟(比如代码中的5秒),以便让主应用有时间优雅地退出。

另外几个需要注意的点:
1. 独立更新器应该保持精简,只包含必要的依赖
2. 要处理好更新器本身的版本管理,避免出现更新器本身也需要更新的情况
3. 可以考虑在安装包里同时打包主应用和更新器,保证它们能同步更新

这个方案虽然稍微复杂一点,但能显著提高自动更新的可靠性。我之前在开发企业级桌面应用时就遇到过类似问题,最后就是用这种方式彻底解决了主进程崩溃导致更新失败的问题。
点赞 8
2026-02-14 10:11