关闭应用后替换asar的exe
//update.bat -> update.exe【Bat To Exe Converter】
@echo off
timeout /T 1 /NOBREAK
del /f /q /a %1\app.asar
ren %1\update.asar app.asar
start "" %2
升级部分
//update.js
const fs = require("fs")
const path = require('path')
const fse = require('fs-extra')
const AdmZip = require("adm-zip");
const { spawn } = require('child_process')
const { app, Notification } = require('electron')
//asar文件所在位置
const asarPath = path.join(__dirname, "../../")
/**
* 启动更新
* @param {*} url 获取版本信息的地址 http://xxxx......
* @param {*} version 当前版本 x.x.x
*/
module.exports.updated = (url, version) => {
//appData应用文件夹
const appPath = path.join(app.getPath('userData'))
//请求版本信息
fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
}).then(
(response) => response.json()
).then((res) => {
/**
* {
* version: "x.x.x",
* url:"http://xxxx......"
* }
*/
const newVersion = res.version
if (newVersion === version) return
info("应用更新中")
const updateUrl = res.url
//获取版本文件
fetch(updateUrl, {
method: "GET",
headers: {
"responseType": 'arraybuffer',
},
})
.then(res => res.blob())
.then(async blob => {
const buffer = Buffer.from(await blob.arrayBuffer());
const zipPath = path.join(appPath, "update.zip")
fs.writeFile(zipPath, buffer, (err) => {
if (!err) {
let exeName = "update.exe"
let exePath = path.join(appPath, exeName)
const exeFromPath = path.join(__dirname, exeName)//升级器存放位置
//更新升级器
fs.copyFile(exeFromPath, exePath, () => { })
const zip = new AdmZip(zipPath);
//解压版本文件到目的地
zip.extractAllTo(asarPath, true);
//关闭应用
setTimeout(()=>{
app.exit(0)
},2000)
}
});
});
}).catch((error) => {
console.error("UPDATE-ERR:", error);
});
}
/**
* 监听应用关闭
*/
app.on('quit', () => {
const updateAsarPath = path.join(asarPath, "update.asar")
//如果更新文件存在
if (fse.pathExistsSync(path.join(app.getPath('userData'), './')) && fse.pathExistsSync(updateAsarPath)) {
const logPath = app.getPath('logs')
const out = fs.openSync(path.join(logPath, './out.log'), 'a')
const err = fs.openSync(path.join(logPath, './err.log'), 'a')
//启动更新器替换asar文件
const child = spawn(`"${path.join(app.getPath('userData'), './update.exe')}"`, [`"${asarPath}"`, `"${app.getPath('exe')}"`], {
detached: true,
shell: true,
stdio: ['ignore', out, err]
})
child.unref()
}
})
const info = (msg) => {
const NOTIFICATION_TITLE = ''
const NOTIFICATION_BODY = msg
new Notification({ title: NOTIFICATION_TITLE, body: NOTIFICATION_BODY }).show()
}
main.js
//main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
let win
const { updated } = require("./update")
const version = "0.0.2"
const createWindow = () => {
win = new BrowserWindow({
frame: true,//关闭原生导航栏
width: 1000,
height: 580,
title: "xxxx", //默认窗口标题 -最低优先级
backgroundColor: "#fff", //窗口背景色 默认-#FFF
autoHideMenuBar: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false, //上下文隔离
}
})
//判断环境 开发环境 or 生产环境
if (process.env.NODE_ENV != 'development') {
win.loadFile(path.join(__dirname, "../dist/index.html"))
} else {
win.loadURL(`${process.env['VITE_DEV_SERVER_URL']}`)
}
updated("http://127.0.0.1:5000/uodate", version)
}
app.whenReady().then(createWindow)
打包的时候生成zip
/**
* 打包的时候将app.asar复制一份,改名成update.asar并压缩(update.zip)
*/
const path = require("path")
const fs = require("fs")
const archiver = require('archiver');
const zipFile = (sourceFile, destZip) => {
let output = fs.createWriteStream(destZip);
let archive = archiver('zip', {
zlib: { level: 9 }
});
archive.pipe(output);
archive.file(sourceFile, {
name: path.basename(sourceFile)
});
archive.finalize();
}
const asarPath = path.join(__dirname, "./release/win-unpacked/resources","app.asar")
const upDataAsarPath = path.join(__dirname, "./release/win-unpacked/resources","update.asar")
const upDataAsarZipPath = path.join(__dirname, "./release","update.zip")
fs.copyFile(asarPath,upDataAsarPath,(err)=>{
if(!err){
zipFile(upDataAsarPath, upDataAsarZipPath)
}
})
传送门
[大佬文章](Electron增量更新(二) - 陌路凡歌 electron 前端的技术分享与个人见解 (xuxin123.com))