Electron增量更新(三)
写Electron这个系列以来,还是有不少同学问了一些问题的,主要是针对于electron增量更新的,之前我写过增量更新(二),但是其Windows方式需要管理员权限包,不太优雅,且如果想要拖拽功能的话,由于权限问题,提权后的软件会禁止拖动(将外部文件拖入软件窗口会有一个禁止图标),那么这一期我会对增量更新进行一次比较详细的说明以及提供临时提权更新的方案供大家参考。
Mac更新
有些同学问了Mac平台下的系统如何增量更新的,实际上Mac下的Electron的asar
文件是可以直接替换的,故下载替换后,开个定时器重启就行了。
Windows
其实我们的桌面软件大都不需要管理员权限的(就是软件上带盾牌的),我们发现很多软件都是在需要更新时会有一个弹窗出现,你点击后会对其进行临时提权进行更新,本期的目标就是实现这种临时提权的功能进行增量更新。
更新问题
其实我们增量更新有两个难点,要想实现得攻克这两个主要问题:
- 什么时候需要uac提权?
- 怎么处理Electron应用启动后
app.asar
被占用锁定的问题?
更新说明
- Windows系统是有不同的用户权限级别的,比如我是普通用户在修改c盘某些文件夹的文件时,会有一个弹窗让你使用管理员权限创建或修改等等,当软件被安装在c盘时,我们就需要管理员权限来替换
app.asar
文件。 - 关于锁定问题,在增量二中已经说明了一下,处理方式就是关闭我们的Electron应用,然后再进行
app.asar
文件的替换。
更新步骤
- 编写bat脚本,在脚本中执行Electron应用的关闭,
app.asar
文件的替换,重启Electron应用,然后将bat脚本打包成exe文件。 - 下载update.asar(更新版本的app.asar),判断用户软件是否安装在c盘,是:使用
sudo-prompt
这个包临时提权执行上面的exe,不是:可以不用提权,直接使用node的exec执行上面的exe。
更新准备
模拟请求什么的前两期更新已经说了,点击这里增量更新(二),看看步骤,这里就不再多做说明。
构建exe
@echo off
taskkill /f /im %3
timeout /T 1 /NOBREAK
del /f /q /a %1\app.asar
move %2\update.asar %1
ren %1\update.asar app.asar
explorer.exe %4
简单解释一下吧,%1和%2为运行脚本传入的参数,比如update.bat aaa bbb
,那么%1为aaa,%2为bbb,上面我们执行exe时传入的,
也就是%1为resourcesPath(也就是我们的app.asar所在目录),%2为下载更新的update.asar所在目录,%3为软件的进程名称(可在任务管理器中查看),%4为软件的启动exe。
这里的逻辑是Electron应用,暂停1秒钟,然后删除app.asar,将update.asar移动到app.asar目录下,重命名为app.asar,启动Electron应用。
下载Bat To Exe Converter这个软件,将update.bat转换为update.exe,详细操作请看前面两期的详细说明。
对比上一期的我们发现启动时没用start命令了,而是用的explorer.exe,它是Windows系统自带的程序管理器,这里的处理是打包的Electron应用不带有管理员权限,但是如果我们提权后执行此exe启动Electron应用,我们会发现此时Electron应用也具有了管理员权限,故需要使用explorer.exe降权启动。
sudo-prompt
安装sudo-prompt,npm i sudo-prompt
,sudo-prompt这个包和node的exec命令差不多,执行时会有一个提权弹窗出现,用户确认后会以管理员权限执行命令,新建sudoPrompt.js:
var sudo = require('sudo-prompt')
var options = {
name: 'Electron',
}
export default (shell) => {
return new Promise((resolve, reject) => {
sudo.exec(shell, options, function(error, stdout, stderr) {
if (error) {
reject(error)
console.log('error:' + error)
return
}
resolve(stdout)
console.log('stdout: ' + stdout)
})
})
}
// npm i https://github.com/xuxingeren/sudo-prompt
"sudo-prompt": "git+https://github.com/xuxingeren/sudo-prompt.git",
注意:sudo-prompt这个包很久没维护了,现在最新的还有一些问题,主要是带有中文路径会出错,原作者已经关闭了提不了pr,我这边处理了一下,使用的话可以fork我的分支来进行构建,地址
主进程更新处理
更新前的准备以及渲染进程处理这里就略过了,请见前面两期内容
import downloadFile from './downloadFile'
import sudoPrompt from './sudoPrompt'
import { app } from 'electron'
const fse = require('fs-extra')
const path = require('path')
const AdmZip = require('adm-zip')
import log from '../config/log.js'
export default async (data) => {
const resourcesPath = process.resourcesPath
// 下载我们上面打包好的更新exe,我这里是放在app.getPath('userData')下的,其他位置也可
if (!fse.pathExistsSync(path.join(app.getPath('userData'), './update.exe'))) {
await downloadFile({
url: data.upDateExe,
targetPath: app.getPath('userData')
}).catch((err) => {
console.log(err)
log.info(err)
})
}
// 提权的方案,这里简写了
const downloads = app.getPath('downloads')
// 下载update.asar,解压(其实不用压缩也可)在系统的下载目录
downloadFile({ url: data.upDateUrl, targetPath: downloads })
.then(async (filePath) => {
const zip = new AdmZip(filePath)
zip.extractAllToAsync(downloads, true, (err) => {
if (err) {
console.error(err)
return
}
fse.removeSync(filePath)
// 这里可以添加判断,如果软件是安装在c盘使用sudoPrompt进行提权执行update.exe,不是的话可以直接执行update.exe
// 临时提权运行exe,exe中关闭主进程,替换安装c盘中的asar(提权是为了处理c盘,如果安装其他盘,可以直接用node.exec运行exe替换)
// 由于提权后的exe打开electron,导致其启动后也会是管理员权限,故需降权进行启动,explorer.exe
// 我博客的编辑器字符串模板解析有问题,美元符号不见了,望谅解
sudoPrompt(
`"${path.join(
app.getPath('userData'),
'./update.exe'
)}" "${resourcesPath}" ${downloads} "${
process.env.VUE_APP_PRODUCTNAME
}.exe" "${app.getPath('exe')}"`
)
})
})
.catch((err) => {
log.info(err)
console.log(err)
})
}
手动调试的话你可以在cmd中执行update.exe xxx xxx xxx xxx
传入对应更新的地址看执行是否成功。
本系列更新只有利用周末和下班时间整理,比较多的内容的话更新会比较慢,希望能对你有所帮助,请多多star或点赞收藏支持一下
用Bat To Exe Converte(https://www.battoexe.com/)这个软件生成的exe会有“请按任意键继续”,是不是的买这个软件啊?博主,期待您的帮助
这个软件官网的试用版是这样的,需要完整版,没条件入正版的话可以网上找找资源
nsis打包的时候可以提权,获取用户的最高权限,也不用装到默认的 program files下,然后child_process里 exec copy /temp/app.asar /resource/app.asar 来实现替换,不用这么麻烦
你好,想加您的联系方式请教一下electron问题可以吗? qq:1938972481