electron 如何升级版本

electron-updater使用指南

基础

检测是否最新版

autoUpdater.checkForUpdates()

下载最新版

autoUpdater.downloadUpdate()

项目使用

update.js

const { ipcMain } = require('electron')
const { autoUpdater } = require('electron-updater')
const path = require("path")
// 更新地址,该地址下放的是安装包和latest.yml
const updateURL = 'https://jkcgy.obs.cn-south-1.myhuaweicloud.com/desktop/'const message = {error: '软件更新异常,请重试',checking: '正在检查更新',updateAva: '检测到新版本,准备下载',updateDown: '软件下载中,请耐心等待',updateSet: '下载完成,准备安装',updateNotAva: '已经是最新版本',
}//软件版本更新
ipcMain.handle('on-soft-update', (e) => {autoUpdater.checkForUpdates()
})
ipcMain.on("updateDesktop", () => {console.log("checkForUpdates");autoUpdater.checkForUpdates()// console.log("downloadUpdate");})
ipcMain.on("updateDesktopping", () => {autoUpdater.downloadUpdate()
})
// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
function handleUpdate(mainWindow, callback) {// 设置是否自动下载,默认是true,当点击检测到新版本时,会自动下载安装包,所以设置为falseautoUpdater.autoDownload = false// 如果安装包下载好了,当应用退出后是否自动安装更新autoUpdater.autoInstallOnAppQuit = falseif (process.env.NODE_ENV == "development") {autoUpdater.updateConfigPath = path.join(__dirname, "../../aaa/app-update.yml");}// 设置版本更新服务器地址autoUpdater.setFeedURL(updateURL)// 更新发生错误时触发autoUpdater.on('error', function () {console.log(" 更新发生错误时触发",);sendUpdateMessage(message.error, "error")})// 开始检查更新事件autoUpdater.on('checking-for-update', function () {console.log(" 开始检查更新事件",);sendUpdateMessage(message.checking, "checking")})// 没有可更新版本autoUpdater.on('update-not-available', function (info) {console.log(" 开始检查更新事件",);sendUpdateMessage(message.updateNotAva, "updateNotAva")})// 发现可更新版本autoUpdater.on('update-available', function (info) {console.log(" 发现可更新版本",);// autoUpdater.downloadUpdate()sendUpdateMessage(message.updateAva, "updateAva")})// 更新下载进度事件autoUpdater.on('download-progress', function (progressObj) {console.log(" 更新下载进度事件",);sendUpdateMessage(message.updateDown, "updateDown")mainWindow.webContents.send('on-soft-download', progressObj.percent)})// 下载监听autoUpdater.on('update-downloaded',function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {mainWindow.webContents.send('on-soft-download', 100)sendUpdateMessage(message.updateSet, "updateSet")//3秒后更新setTimeout(() => {autoUpdater.quitAndInstall()}, 3000)})// 向渲染进程发送消息function sendUpdateMessage(text, type) {mainWindow.webContents.send('on-soft-message', text, type)}
}module.exports = {handleUpdate,
}

然后再 main.js 调用即可

  mainWindow.on('ready-to-show', () => {mainWindow.show();updater.handleUpdate(mainWindow)if (!ipc) ipc = new IPC(mainWindow);mainWindow.openDevTools();// if(!callWindowIpc) callWindowIpc = new CallWindowIpc(mainInstance);});

main.js 所有代码

const { app, BrowserWindow, ipcMain, globalShortcut, Tray, Menu } = require('electron');
const Store = require('electron-store');
const CaptureView = require('./electron-captureview/main/captureview').default;
const path = require('path');
const url = require('url');
const TimMain = require('im_electron_sdk/dist/main');
const { SDK_APP_ID, GET_FILE_INFO_CALLBACK, SCREENSHOTMAC } = require('./const/const');
const IPC = require('./ipc');
const CallWindowIpc = require('./callWindowIpc');
const child_process = require('child_process')
const fs = require('fs')
const updater= require("./update")
const store = new Store();
Store.initRenderer();
const { autoUpdater } = require('electron-updater')process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';let callWindowIpc;
let ipc;
let mainInstance;
let catchedSdkAppId;
const settingConfig = store.get('setting-config');
const sdkappid = catchedSdkAppId = settingConfig?.sdkappId ?? SDK_APP_ID;let tray = null  // 在外面创建tray变量,防止被自动删除,导致图标自动消失const initTimMain = (appid) => {mainInstance = new TimMain({sdkappid: Number(appid)});
}initTimMain(sdkappid);const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));ipcMain.handle('re-create-main-instance', async (event, newSdkAppid) => {console.log("************ re-create-main-instance", newSdkAppid)mainInstance.setSDKAPPID(newSdkAppid)return
})// This allows TypeScript to pick up the magic constant that's auto-generated by Forge's Webpack
// plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on
// whether you're running in development or production).
// declare const MAIN_WINDOW_WEBPACK_ENTRY: string;// Handle creating/removing shortcuts on Windows when installing/uninstalling.
// app.on('window-all-closed', function () {
//   if (process.platform !== 'darwin') app.quit()
// })const createWindow = () => {// Create the browser window.const mainWindow = new BrowserWindow({height: 628,width: 975,minWidth: 975,minHeight: 628,// show:false,icon: path.resolve(__dirname, "../../icon/logo.png"),frame: false,webPreferences: {webSecurity: true,nodeIntegration: true,nodeIntegrationInWorker: true,enableRemoteModule: true,contextIsolation: false,}});mainInstance.enable(mainWindow.webContents)global.WIN = mainWindow;mainWindow.on('ready-to-show', () => {mainWindow.show();updater.handleUpdate(mainWindow)if (!ipc) ipc = new IPC(mainWindow);mainWindow.openDevTools();// if(!callWindowIpc) callWindowIpc = new CallWindowIpc(mainInstance);});mainWindow.on('close', (e) => {// mainWindow.webContents.send('updateHistoryMessage');// setTimeout(() => {//   app.exit();// }, 30);e.preventDefault();  // 阻止退出程序mainWindow.setSkipTaskbar(true)   // 取消任务栏显示mainWindow.hide();    // 隐藏主程序窗口});console.log('======process env======', process.env?.NODE_ENV);if (process.env?.NODE_ENV?.trim() === 'development') {mainWindow.loadURL(`http://localhost:3000`);mainWindow.webContents.openDevTools();} else {mainWindow.loadURL(url.format({pathname: path.join(__dirname, '../../bundle/index.html'),protocol: 'file:',slashes: true}));}// 创建任务栏图标tray = new Tray(path.join(__dirname, "../../icon/logo.png"))// 自定义托盘图标的内容菜单const contextMenu = Menu.buildFromTemplate([{// 点击退出菜单退出程序label: '退出', click: function () {mainWindow.webContents.send('updateHistoryMessage');setTimeout(() => {app.exit();}, 30);// mainWindow.destroy()}}])tray.setToolTip('君凯智管')  // 设置鼠标指针在托盘图标上悬停时显示的文本tray.setContextMenu(contextMenu)  // 设置图标的内容菜单// 点击托盘图标,显示主窗口tray.on("click", () => {mainWindow.show();mainWindow.setSkipTaskbar(false)   // 取消任务栏显示})// const capture = new CaptureView({//   devTools: false,//   Mosaic: false,//   Text: false,//   // onShow: () => {//   //   console.log('start screenshot');//   // },//   onClose: () => {//    const png = clipboard.readImage().toBitmap();//    const fileExample = new File([png], 'xxx.png', { type: 'image/jpeg' });//     console.log('结束截图', fileExample);//   },//   onShowByShortCut: () => {//     console.log('shortcut key to start screenshot')//   }// });// capture.setMultiScreen(true);// capture.updateShortCutKey('shift+option+c');globalShortcut.register('Shift+CommandOrControl+C', function () {console.log("i am shortcut~~~~~~~~~");const newdate = new Date();const date = newdate.toISOString().replaceAll(":", "");// console.log(date.toISOString());if (process.platform == "darwin") {let ex = "screencapture -i ~/desktop/screenshot" + date + ".png"child_process.exec(`screencapture -i ~/desktop/screenshot` + date + `.png`, (error, stdout, stderr) => {if (!error) {var _img = fs.readFileSync(process.env.HOME + "/desktop/screenshot" + date + ".png");// console.log(_img);mainWindow.webContents.send(GET_FILE_INFO_CALLBACK, {triggerType: SCREENSHOTMAC,data: { _img: _img, date }})}});} else {let url = path.resolve(__dirname, "../Snipaste-2.8.2-Beta-x64/Snipaste.exe");let command = url + " snip -o C:\\Users\\Public\\Desktop\\screenshot" + date + ".png";// console.log(command);var id = setInterval(dealFile, 300);child_process.exec(command, async (error, stdout, stderr) => {if (!error) {console.log("done capture");}})function dealFile() {try {var _img = fs.readFileSync("C:\\Users\\Public\\Desktop\\screenshot" + date + ".png");clearInterval(id);console.log("file exists");console.log(_img);event.reply(GET_FILE_INFO_CALLBACK, {triggerType: SCREENSHOTMAC,data: { _img: _img, date }})} catch (err) {if (err.code == 'ENOENT') {// console.log("file doesn't exist yet")} else {throw err;}}}}})// mainWindow.loadURL(`http://localhost:3000`);// mainWindow.webContents.openDevTools();
};// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);Object.defineProperty(app, 'isPackaged', {get() {return true;}
});// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {console.log('all-window-closed');if (process.platform !== 'darwin') {app.exit();}
});app.on('activate', () => {// On OS X it's common to re-create a window in the app when the// dock icon is clicked and there are no other windows open.if (BrowserWindow.getAllWindows().length === 0) {createWindow();}
});// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.

常见错误指南

Electron更新报错-Skip checkForUpdates because application is not packed and dev update config is not forced

原因是在本地启动的不是安装导致的,在根中配置即可

const { app, BrowserWindow, ipcMain, globalShortcut, Tray, Menu } = require('electron');Object.defineProperty(app, 'isPackaged', {get() {return true;}
});

Electron更新报错-

必须设置这个内容

  "publish": [{"provider": "generic","channel": "latest","url": "https://jkcgy.obs.cn-south-1.myhuaweicloud.com/desktop/%E5%90%9B%E5%87%AF%E6%99%BA%E7%AE%A1%20Setup%200.0.2.exe"}],

Electron更新报错-UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open '****\app-update.yml'

找不到app-update.yml 文件,可以去打包路径中的 dist\win-unpacked\resources 复制,然后通过修改  autoUpdater.updateConfigPath 路径 

 该路径是自定义的路径,自己在 dist\win-unpacked\resources 复制的

const { autoUpdater } = require('electron-updater') autoUpdater.updateConfigPath = path.join(__dirname, "../../aaa/app-update.yml");

Electron更新报错-找不到latest.yml 文件

找不到latest.yml文件 可以去dist 复制

这里跟配置的 autoUpdater.setFeedURL 路径有关系

const { autoUpdater } = require('electron-updater')
const updateURL = 'https://jkcgy.obs.cn-south-1.myhuaweicloud.com/desktop/'// 设置版本更新服务器地址
autoUpdater.setFeedURL(updateURL)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/843619.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Wpf 使用 Prism 实战开发Day27

首页汇总和数据动态显示 一.创建首页数据汇总数据接口 汇总:待办事项的总数已完成:待办事项里面有多少条完成的待办完成比例:已完成和汇总之间的比例备忘录:显示备忘录的总数待办事项:显示待办事项未完成的集合备忘录&…

②单细胞学习-组间及样本细胞比例分析

目录 数据读入 每个样本各细胞比例 两个组间细胞比例 亚组间细胞比例差异分析(循环) 单个细胞类型亚新间比例差异 ①单细胞学习-数据读取、降维和分群-CSDN博客 比较各个样本间的各类细胞比例或者亚组之间的细胞比例差异 ①数据读入 #各样本细胞…

三、Ollama导入大模型(.Net8+SemanticKernel+Ollama)本地运行自己的大模型

Ollama导入大模型 一、导入Ollama大模型1、使用run命令2、使用Modelfile方式 二、导入自定义大模型(Ollama官网以外的大模型)三、使用OpenWebUI导入大模型 Ollama可以导入官方提供的大模型,也可以导入huggingface上的自定义大模型&#xff08…

【加密与解密(第四版)】第十四章笔记

第十四章 漏洞分析技术 14.1 软件漏洞原理 缓冲区溢出漏洞:栈溢出 堆溢出、整型溢出(存储溢出、计算溢出、符号问题) UAF(Use-After-Free)漏洞 14.2 ShellCode 功能模块:下载执行、捆绑、反弹shell 14.3 …

【NumPy】使用NumPy计算相关系数:详解numpy.corrcoef函数及应用

🧑 博主简介:阿里巴巴嵌入式技术专家,深耕嵌入式人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍:分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向…

MySQL之性能剖析(二)

MySQL之性能剖析 通过性能剖析进行优化 一旦掌握并时间面向响应时间的优化方法,就会发现需要不断地对系统进行性能剖析(profiling). 性能剖析是测量和分析时间花费在哪里的主要方法。性能剖析一般有两个步骤:测量任务所花费的时间;然后对结果进行统计和…

基础8 探索JAVA图形编程桌面:邮件操作组件详解

在一个静谧的午后,卧龙和凤雏相邀来到一家古朴典雅的茶馆。茶馆内环境清幽,袅袅的茶香与悠扬的古筝声交织在一起,营造出一种宁静而祥和的氛围。 卧龙和凤雏坐在茶馆的一角,面前的桌子上摆放着一套精致的茶具。茶香四溢&#xff0c…

C++ STL 中的自定义比较:深入理解相等和等价

STL 中的自定义比较、相等和等价 一、简介二、STL 的排序部分三、STL 的未排序部分四、比较元素五、实现比较器六、总结 一、简介 本文主要讨论了在 STL 中使用自定义比较函数&#xff0c;以及比较操作中的相等和等价概念。 有如下的代码&#xff1a; std::vector< std::…

HTML并集,交集,子代,后代选择器

1,交集选择器 他们必须满足既是p又是.box的关系&#xff08;直接连写&#xff0c;没有任何符号&#xff09; p.box{color:red; } <div class"box"> 1 </div> <p class"box">2</p> <p>3</p> 2.并集选择器 将div,p,…

【强化学习04】Q学习时序差分法

贝尔曼方程在强化学习中是用来更新Q值&#xff08;动作价值&#xff09;的一个重要工具。下面用小白能理解的方式解释贝尔曼方程是如何更新Q值的&#xff1a; 什么是Q值&#xff1f; 在强化学习中&#xff0c;Q值是用来评估在某个状态&#xff08;state&#xff09;下执行某个…

牛客题目进展

提示&#xff1a;文章 文章目录 前言一、背景二、 2.1 2.2 总结 前言 前期疑问&#xff1a; 本文目标&#xff1a; 一、背景 最近想整理一下牛课进度&#xff0c;顺便看了下表格绘制方法 绘制表格方法&#xff1a;绘制表格 二、 2.1 牛客序号题目知识点难度状态链接其…

【C++】牛客——活动安排

✨题目链接&#xff1a; AB31 活动安排 ✨题目描述 给定&#x1d45b;个活动&#xff0c;每个活动安排的时间为[&#x1d44e;&#x1d456;,&#x1d44f;&#x1d456;)。求最多可以选择多少个活动&#xff0c;满足选择的活动时间两两之间没有重合。 ✨输入描述: 第一行…

北交所的股票交易佣金最低是多少?万分之二算低的吗?

北交所的佣金目前最低是万分之二&#xff0c;不过只有少数证券公司是这个标准。普通股票佣金万1&#xff0c;融资利率是4.0%~5.0%&#xff01; 北交所佣金一般是万分之6&#xff0c;北交所全称是北京证券交易所&#xff0c;是一家公司制交易所&#xff0c;北交所的佣金比普通股…

【JVM底层原理,JVM架构详解】

1. JVM简介 1.1 什么是JVM? JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 主流虚拟机: 虚拟机名称介绍HotSpotOracle/Sun JDK和OpenJDK都使用HotSPo…

人大金仓python驱动安装指引

最好使用虚拟环境&#xff0c;避免各种路径异常问题 在指定目录下创建虚拟环境 python3 -m venv myenv myenv可以是一个路径&#xff0c;当前命令会创建一个叫myenv的目录&#xff0c;目录里放的是虚拟环境所需的可执行文件 激活虚拟环境 source myenv/bin/activate 退出虚…

2024-05-28 服务器开发-不同vs版本的std::string的访问出错问题-记录

摘要: 有一个dll库是使用vs2010编译的, 使用这个dll动态库的工程是vs2019. 这个dll动态库返回一个结构体&#xff0c;其中有个成员使用了std::string。但是遇到了std::string的成员显示被赋值为NULL的情况。 本文对进行分析, 重点在于追踪问题的思路。 问题描述: dll使用vs20…

保护“第二生命线”,科技守护颈椎健康

脊柱支撑着人体重量&#xff0c;汇集着众多血管神经&#xff0c;素有“人体第二生命线”之称。在如今快节奏的时代&#xff0c;人们生活方式也在发生着变化&#xff0c;长期低头看手机、伏案久坐等不良生活习惯引发脊柱健康问题&#xff0c;且呈现年轻化趋势。目前&#xff0c;…

vue小记——上传图片小组件

个人笔记 前端&#xff1a; <template><el-uploadclass"avatar-uploader"name"image"action"http://127.0.0.1:3000/api/image/upload":show-file-list"false":headers"headerObj":data"DataForm":on-s…

【加密与解密(第四版)】第十二章笔记

第十二章 注入技术 12.1 DLL注入方法 在通常情况下&#xff0c;程序加载 DLL的时机主要有以下3个&#xff1a;一是在进程创建阶段加载输入表中的DLL&#xff0c;即俗称的“静态输人”;二是通过调用 LoadLibrary(Ex)主动加载&#xff0c;称为“动态加载”&#xff1b;三是由于系…

核心三:正确的停止线程

3、核心三&#xff1a;正确的停止线程 3.1 如何正确的停止线程 3.1.1 原理介绍&#xff1a;使用interrupt来通知&#xff0c;而不是强制 线程中断的机制&#xff1a;一个线程来通知要中断线程&#xff08;你好&#xff0c;你现在应该停止了&#xff09;最后的决定是由要中断…