1.安装依赖:
npm install electron-updater --save
2.main.js:
1)创建窗口
const {
app,
protocol,
BrowserWindow,
crashReporter,
shell,
Menu,
ipcMain,
Tray,
globalShortcut
} = require('electron')
// 全局浏览器对象
let win
function createWindow (args = {}) {
if (win) {
win.close()
// win.show()
// win.focus()
// win.webContents.send('updateChat', args)
// return
}
win= new BrowserWindow({
x: 0,
y: 0,
resizable: true,
show: false,
// titleBarStyle: 'hidden',//是否显示顶部的菜单
autoHideMenuBar: false,//时候隐藏操作按钮
useContentSize: true,
center: false,
transparent: false,
webPreferences: {
nodeIntegration: true,
nativeWindowOpen: true,
contextIsolation: false,
webSecurity: false
},
icon: `${__static}/icon/favicon.ico`
})
win.loadURL('app://./index.html')
// 调试模式
// win.webContents.openDevTools()
// globalShortcut.register('ctrl+shift+i', function () {
// win.webContents.openDevTools() // 打开F12调试页面
// })
win.once('ready-to-show', () => {
win.show()
win.focus()
win.webContents.send('updateChat', args)
if (win.isMaximized()) {
win.unmaximize()
} else {
win.maximize()
}
})
win.on('close', e => {
win= null
})
const menu = Menu.buildFromTemplate([])//自定义菜单
Menu.setApplicationMenu(menu)
}
2)更新方法
import {autoUpdater} from "electron-updater"
const isDevelopment = process.env.NODE_ENV !== 'production'
/**
* ipc事件
*/
function ipcEventInit () {
// 最小化
ipcMain.on('min', e => win.minimize())
// 最大化
ipcMain.on('max', e => {
if (win.isMaximized()) {
win.unmaximize()
} else {
win.maximize()
}
})
// 关闭
ipcMain.on('close', e => win.minimize())
// 执行自动更新检查(通过接口控制,如果接口发现版本号,执行更新)
//$electron.ipcRenderer.send("checkForUpdate", url)
ipcMain.on('checkForUpdate', (event, url) => {
win && win.webContents.send('upPackgeMsg', {
status: 999,
message: `执行自动更新检查……[${url}]`
})
//设置检查更新的链接
autoUpdater.setFeedURL(url)
setTimeout(()=>{
autoUpdater.checkForUpdates()
},0)
})
// 开始更新
ipcMain.on('isUpdateNow', () => {
win && win.webContents.send('upPackgeMsg', {
status: 999,
message: '开始更新……'
})
win.webContents.send('quit');
autoUpdater.quitAndInstall(true, true) // 安装文件
if(win && win.destroy){
win.destroy()
}
app.quit()
})
// 打开外部链接
ipcMain.on('openLink', (event, params) => {
shell.openExternal(params)
})
}
// 自动检测更新
function handleUpdate () {
// 更新地址
const message = {
error: {
status: -1,
message: '检查更新出错'
},
success: {
status: 1,
message: '更新完成'
}
}
// 设置是否自动下载,默认是true
autoUpdater.autoDownload = true
autoUpdater.autoInstallOnAppQuit = true // 如果安装包下载好了,那么当应用退出后是否自动安装更新
if (process.env.NODE_ENV === 'development') {
autoUpdater.updateConfigPath = path.join(
__dirname,'/win-unpacked/resources/app-update.yml'
)
} else {
autoUpdater.updateConfigPath = path.join(__dirname, '../app-update.yml')
}
// 更新失败
autoUpdater.on('error', function () {
//发送消息 接口:$electron.ipcRenderer.on("upPackgeMsg",(event,msg)=>{})
win && win.webContents.send('upPackgeMsg', message.error)
})
// 开始执行检查更新
autoUpdater.on('checking-for-update', function () {
//发送消息
win && win.webContents.send('upPackgeMsg', {
status: 3,
message: '开始检查版本……'
})
})
// 检测到新版本
autoUpdater.on('update-available', function (info) {
let updaterCacheDirName = 'xxx_app-updater'
// 有更新,删除本地安装包
const updatePendingPath = path.join(
autoUpdater.app.baseCachePath,
updaterCacheDirName,
'pending'
)
fs.emptyDir(updatePendingPath)
//发送消息
win && win.webContents.send('upPackgeMsg', {
status: 4,
message: '检测到新版本……'
})
})
//没有更新的
autoUpdater.on('update-not-available', function (info) {
//发送消息
win && win.webContents.send('upPackgeMsg', {
status: 5,
message: '当前以及是最新版本……'
})
})
// 更新下载进度事件
autoUpdater.on('download-progress', function (progressObj) {
//发送消息
win && win.webContents.send('upPackgeMsg', {
status: 2,
message: '下载文件中……',
progress: progressObj.percent
})
})
//更新下载成功
autoUpdater.on('update-downloaded', function (
event,
releaseNotes,
releaseName,
releaseDate,
updateUrl,
quitAndUpdate
) {
//发送消息
win && win.webContents.send('upPackgeMsg', message.success)
})
}
3) 挂载更新和ipc事件
/**
* 主进程生命周期
*/
app.on('ready', async () => {
//创建窗口
createWindow()
// 开机自启配置
// app.setLoginItemSettings({
// openAtLogin: true,
// openAsHidden: true,
// path: process.execPath,
// args: ['--processStart', `"${exeName}"`]
// })
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
// 当运行第二个实例时,将会聚焦到mainWindow这个窗口
if (win) {
if (win.isMinimized()) win.restore()
win.focus()
win.show()
}
})
}
// 注册ipc事件
ipcEventInit()
// 初始化Update配置
handleUpdate()
})
3.package.json 或者 vue.config.js (需要配置publish,否则就不生成latest.yml)
module.exports = {
pluginOptions: {
electronBuilder: {
builderOptions: {
//更新需要的配置
publish: [
{
provider: 'generic',
url: ''
}
],
appId: '',
//其他配置
win: {
requestedExecutionLevel: 'highestAvailable',
icon: './public/icon/favicon.ico',
target: [
{
target: 'nsis',
arch: [
// 这个意思是打出来32 bit + 64 bit的包,但是要注意:这样打包出来的安装包体积比较大,所以建议直接打32的安装包。
'x64'
]
}
]
},
mac: {
target: ['dmg', 'zip'],
category: 'public.app-category.business',
icon: './public/icon/favicon.png',
entitlements: "entitlements.mac.plist",
hardenedRuntime: true,
extendInfo: {
NSMicrophoneUsageDescription: "请允许本程序访问您的麦克风",
NSCameraUsageDescription: "请允许本程序访问您的摄像头"
}
},
linux: {
icon: './public/icon',
},
nsis: {
oneClick: false, // 一键安装
perMachine: false, // 是否开启安装时权限限制(此电脑或当前用户)
allowElevation: true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
allowToChangeInstallationDirectory: true, // 允许修改安装目录
installerIcon: './public/icon/favicon.ico', // 安装图标
uninstallerIcon: './public/icon/favicon.ico', // 卸载图标
installerHeaderIcon: './public/icon/favicon.ico', // 安装时头部图标
createDesktopShortcut: true, // 创建桌面图标
createStartMenuShortcut: true, // 创建开始菜单图标
shortcutName: '', // 图标名称
// artifactName:'${productName}${version}.${ext}'//不可如此
// artifactName:'${productName}.${ext}'
artifactName: '${productName} Setup ${version}.${ext}'
},
productName: ''//安装包名称
},
target: "electron-renderer"
}
}
}
4.autoUpdater实现exe更新的时候需要再服务器上部署个人站点,需要以下几个文件
---latest.yml (高版本bulider的时候生成)
---xxx_1.0.0.exe.blockmap(当前版本bulider生成)
---xxx_1.3.0.exe(高版本bulider生成)
---xxx_1.3.0.exe.blockmap(高版本bulider生成)