# 十、程序保护
https://segmentfault.com/a/1190000007503495
# 10.1 崩溃
崩溃监控是每个客户端程序必备的保护功能,当程序崩溃时我们一般期望做到两件事:
- 1.上传崩溃日志,及时报警
- 2.监控程序崩溃,提示用户重启程序
electron
为我们提供给了crashReporter
来帮助我们记录崩溃日志,我们可以通过crashReporter.start
来创建一个崩溃报告器:
const { crashReporter } = require("electron");
crashReporter.start({
productName: "YourName",
companyName: "YourCompany",
submitURL: "https://your-domain.com/url-to-submit",
uploadToServer: true,
});
1
2
3
4
5
6
7
2
3
4
5
6
7
当程序发生崩溃时,崩溃报日志将被储存在临时文件夹中名为YourName Crashes
的文件文件夹中。submitURL
用于指定你的崩溃日志上传服务器。 在启动崩溃报告器之前,您可以通过调用app.setPath('temp', 'my/custom/temp')
API 来自定义这些临时文件的保存路径。你还可以通过crashReporter.getLastCrashReport()
来获取上次崩溃报告的日期和ID
。
我们可以通过webContents
的crashed
来监听渲染进程的崩溃,另外经测试有些主进程的崩溃也会触发该事件。所以我们可以根据主window
是否被销毁来判断进行不同的重启逻辑,下面使整个崩溃监控的逻辑:
import { BrowserWindow, crashReporter, dialog } from "electron";
// 开启进程崩溃记录
crashReporter.start({
productName: "electron-react",
companyName: "ConardLi",
submitURL: "http://xxx.com", // 上传崩溃日志的接口
uploadToServer: false,
});
function reloadWindow(mainWin) {
if (mainWin.isDestroyed()) {
app.relaunch();
app.exit(0);
} else {
// 销毁其他窗口
BrowserWindow.getAllWindows().forEach((w) => {
if (w.id !== mainWin.id) w.destroy();
});
const options = {
type: "info",
title: "渲染器进程崩溃",
message: "这个进程已经崩溃.",
buttons: ["重载", "关闭"],
};
dialog.showMessageBox(options, (index) => {
if (index === 0) mainWin.reload();
else mainWin.close();
});
}
}
export default function () {
const mainWindow = BrowserWindow.fromId(global.mainId);
mainWindow.webContents.on("crashed", () => {
const errorMessage = crashReporter.getLastCrashReport();
console.error("程序崩溃了!", errorMessage); // 可单独上传日志
reloadWindow(mainWindow);
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 10.2 最小化到托盘
有的时候我们并不想让用户通过点关闭按钮的时候就关闭程序,而是把程序最小化到托盘,在托盘上做真正的退出操作。
首先要监听窗口的关闭事件,阻止用户关闭操作的默认行为,将窗口隐藏。
function checkQuit(mainWindow, event) {
const options = {
type: "info",
title: "关闭确认",
message: "确认要最小化程序到托盘吗?",
buttons: ["确认", "关闭程序"],
};
dialog.showMessageBox(options, (index) => {
if (index === 0) {
event.preventDefault();
mainWindow.hide();
} else {
mainWindow = null;
app.exit(0);
}
});
}
function handleQuit() {
const mainWindow = BrowserWindow.fromId(global.mainId);
mainWindow.on("close", (event) => {
event.preventDefault();
checkQuit(mainWindow, event);
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
这时程序就再也找不到了,任务托盘中也没有我们的程序,所以我们要先创建好任务托盘,并做好事件监听。
windows 平台使用
ico
文件可以达到更好的效果
export default function createTray() {
const mainWindow = BrowserWindow.fromId(global.mainId);
const iconName = process.platform === "win32" ? "icon.ico" : "icon.png";
tray = new Tray(path.join(global.__dirname, iconName));
const contextMenu = Menu.buildFromTemplate([
{
label: "显示主界面",
click: () => {
mainWindow.show();
mainWindow.setSkipTaskbar(false);
},
},
{
label: "退出",
click: () => {
mainWindow.destroy();
app.quit();
},
},
]);
tray.setToolTip("electron-react");
tray.setContextMenu(contextMenu);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
文中如有错误,欢迎在评论区指正,如果这篇文章帮助到了你,欢迎点赞和关注。