首页/文章/electron

Electron增量更新3

2024-07-29
16696 分钟
...

写Electron这个系列以来,还是有不少同学问了一些问题的,主要是针对于electron增量更新的,之前我写过增量更新(二),但是其Windows方式需要管理员权限包,不太优雅,且如果想要拖拽功能的话,由于权限问题,提权后的软件会禁止拖动(将外部文件拖入软件窗口会有一个禁止图标),那么这一期我会对增量更新进行一次比较详细的说明以及提供临时提权更新的方案供大家参考。

Mac更新

有些同学问了Mac平台下的系统如何增量更新的,实际上Mac下的Electron的asar文件是可以直接替换的,故下载替换后,开个定时器重启就行了。

Windows

其实我们的桌面软件大都不需要管理员权限的(就是软件上带盾牌的),我们发现很多软件都是在需要更新时会有一个弹窗出现,你点击后会对其进行临时提权进行更新,本期的目标就是实现这种临时提权的功能进行增量更新。

更新问题

其实我们增量更新有两个难点,要想实现得攻克这两个主要问题:

  1. 什么时候需要uac提权?
  2. 怎么处理Electron应用启动后app.asar被占用锁定的问题?

更新说明

  1. Windows系统是有不同的用户权限级别的,比如我是普通用户在修改c盘某些文件夹的文件时,会有一个弹窗让你使用管理员权限创建或修改等等,当软件被安装在c盘时,我们就需要管理员权限来替换app.asar文件。

  2. 关于锁定问题,在增量二中已经说明了一下,处理方式就是关闭我们的Electron应用,然后再进行app.asar文件的替换。

更新步骤

  1. 编写bat脚本,在脚本中执行Electron应用的关闭,app.asar文件的替换,重启Electron应用,然后将bat脚本打包成exe文件。
  2. 下载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)
    })
  })
}


"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
  
  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')
  
  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)
        
        
        
        
        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或点赞收藏支持一下

本文地址:链接
本文github地址:链接

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
electron2025-03-05
不依赖第三方库自己实现 Electron 的主与渲染进程的国际化功能
正文 直接贴出代码: 主进程实现 首先需要在 文件中获取当前系统的语言,然后初始化国际化相关: 文件: 文件 然后在主进程中就可以通过 来实现国际化了。 渲染进程的实现 App 在启动的时候渲染进程已经执行了国际化的初始化,所以在主进程已经保存了一份当前语言的 信息,所以渲染进程就不需要进程这一步,直接从主进程获取即可。 主进程进程添加一个 事件,供渲染进程获取国际化相关数据: 首先我们要在 preload 中提前将国际化相关的信息写入...
学习
electron2025-03-05
应用多开,限制只启动一个应用,防止多个实例
通过app.requestSingleInstanceLock来控制应用的多开,返回值为boolean。 此方法的返回值表示你的应用程序实例是否成功取得了锁。如果它取得锁失败,你可以假设另一个应用实例已经取得了锁并且仍旧在运行,并立即退出。 即:如果当前进程是应用程序的主要实例,则此方法返回true,同时你的应用会继续运行。如果当它返回false,如果你的程序没有取得锁,它应该立刻退出,并且将参数发送给那个已经取到锁的进程。 在macO...
学习
electron2024-09-23
Electron实现文件缓存背景
背景 基于Electron研发的一款IM企业通信桌面端应用,会存在非常多文件、图片、视频类型回话消息。在Electron应用(桌面客户端软件)中,快速加载并显示图片是提升用户体验的关键。然而,传统的图片加载方式往往存在加载速度慢、资源占用高等问题,影响了用户的使用体验。 解决的问题 1. 支持自定义配置存储的磁盘位置 2. 支持长期存储 3. 支持自定义存储大小 4. 支持自定义存储类型(如图片、视频、文件,或者更细致化到MIME) 5...
学习
electron2024-09-23
我的 Electron 客户端也可以全量和增量更新了
前言 本文主要介绍 客户端应用的自动更新,包括全量和增量这两种方式。 全量更新: 运行新的安装包,安装目录所有资源覆盖式更新。 增量更新: 只更新修改的部分,通常是渲染进程和主进程文件。 本文并没有拿真实项目来举例子,而是起一个 新的项目 从 0 到 1 来实现自动更新。 如果已有的项目需要支持该功能,借鉴本文的主要步骤即可。 前置说明: 1. 由于业务场景的限制,本文介绍的更新仅支持 操作系统,其余操作系统未作兼容处理。 2. 更新流...
学习
electron2024-09-20
我的 Electron 客户端被第三方页面入侵了
问题描述 公司有个内部项目是用 来开发的,有个功能需要像浏览器一样加载第三方站点。 本来一切安好,但是某天打开某个站点的链接,导致 整个客户端直接变成了该站点的页面 。 这一看就是该站点做了特殊的处理,经排查网页源码后,果然发现了有这么一句代码。 翻译一下就是:如果当前窗口不是顶级窗口的话,将当前窗口设置为顶级窗口。 奇怪的是两者不是 跨域 了吗,为什么 还可以影响顶级窗口。 先说一下我当时的一些解决办法: 1. 用 替换 2. 给 添...
学习
electron2024-09-13
Electron+WebRTC实现局域网内的远程控制软件
我的工位上有一台笔记本(windows),一个显示器,一台服务器(linux)。显示器同时连接笔记本和服务器,当需要用到服务器的时候:1.使用todesk等软件进行连接;2.直接把显示器切换到服务器桌面,然后给服务器插上鼠标键盘。在这种场景下,屏幕画面的传输对我来说并不是必要的,这种场景下能不能用一套键鼠控制两个电脑呢?边做边学便有了这个小工具。记录下来,其中遇到的问题和解决方案。 通过electron + Vue + primevue...
学习

评论

请登录后发表评论

去登录
加载评论中...

目录