vue2.0+electron+electron-builder+electron-updater实现打包成exe桌面应用并自动更新

1.版本

Node (20.12.2)
Npm (10.5.2)
Vue  (2.6.4)
Eelectron第三方库 (31.2.1)
electron-builder 打包工具 (13.6.9)
electron-updater 自动更新依赖 (6.2.1)

2.打包成exe文件实现步骤

2.1 安装electron

npm i electron

2.2 添加打包工具

vue add electron-builder

安装后src下会自动生成background.js文件

package.json生成对应的命令
并把background.js作为入口文件

package.json修改如下内容(解决打包不成功的问题)

将  
"electron:build": "vue-cli-service electron:build",
改成
"electron:build": "set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service electron:build",

2.3 命令

运行命令:npm run electron:serve

打包命令:npm run electron:build

2.4 解决打包时的报错问题

1.下载与当前版本一致的electron-v13.6.9-win32-x64,放在C:\Users\DELL\AppData\Local\electron\Cache 下


2.下载对应的winCodeSign 解压后放在

C:\Users\DELL\AppData\Local\electron-builder\Cache\winCodeSign 下


3.下载对应nsis 解压后放在

C:\Users\DELL\AppData\Local\electron-builder\Cache\nsis 下

注:可以复制错误提示里面的链接下载相关文件

2.5 打包后生成的文件

双击exe文件安装成桌面端应用

3.自动更新实现步骤

3.1配置生成latest.yml文件

注:只有配置了以下内容,在打包的时候才会产生latest.yml这个文件,这个文件就是对安装包版本的一个描述,在进行版本比对的时候 就是在读取这个文件的内容,才能够实现自动更新

vue.config.js文件

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
  pluginOptions: {
    electronBuilder: {
      customFileProtocol: "./", //解决打包之后elementui不显示icon图标
      nodeIntegration: true,
      builderOptions: {
        nsis: {
          allowToChangeInstallationDirectory: true, //自定义安装路径
          oneClick: false, 
          allowElevation: false,//安装时不请求管理员
          perMachine: true, // 避免安装时的用户选择
          createDesktopShortcut: true, // 创建桌面快捷方式
          runAfterFinish: true, // 安装完成后运行
        },
        win: {
          publish: [{
            provider: "generic",
            url: "http://192.168.3.43/dist/", //更新包服务器上地址  

          }],
        },
        productName: '智能刀具监测系统'  //项目名
      }
    },
  },
})

将latest.yml文件和生成的.exe文件放在服务器上,会自动检测版本 

 

 3.2 安装自动更新依赖electron-updater

npm i electron-updater

3.3 自动更新代码 

3.3.1 在background.js同级目录下创建handleUpdate.js文件

import {
    autoUpdater
} from 'electron-updater'

import {
    ipcMain, dialog
} from 'electron'
let mainWindow = null;
export function handleUpdate(window, feedUrl) {
    mainWindow = window;
    let message = {
        error: '检查更新出错',
        checking: '正在检查更新……',
        updateAva: '检测到新版本,正在下载……',
        updateNotAva: '现在使用的就是最新版本,不用更新',
    };

    `autoUpdater.autoDownload = false;` //取消自动下载
    //设置更新包的地址
    autoUpdater.setFeedURL(feedUrl);
    //监听升级失败事件
    autoUpdater.on('error', function (error) {
        sendUpdateMessage({
            cmd: 'error',
            message: error
        })
    });
    //监听开始检测更新事件
    autoUpdater.on('checking-for-update', function (message) {
        sendUpdateMessage({
            cmd: 'checking-for-update',
            message: message
        })
    });
    //监听发现可用更新事件
    autoUpdater.on('update-available', function (message) {
        sendUpdateMessage({
            cmd: 'update-available',
            message: message
        })
    });
    //监听没有可用更新事件
    autoUpdater.on('update-not-available', function (message) {
        sendUpdateMessage({
            cmd: 'update-not-available',
            message: message
        })
    });

    // 更新下载进度事件
    autoUpdater.on('download-progress', function (progressObj) {
        sendUpdateMessage({
            cmd: 'download-progress',
            message: progressObj
        })
    });
    //监听下载完成事件
    autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl) {
        sendUpdateMessage({
            cmd: 'update-downloaded',
            message: {
                releaseNotes,
                releaseName,
                releaseDate,
                updateUrl
            }
        })

        //退出并安装更新包
        autoUpdater.quitAndInstall();
    });
    //新增
    ipcMain.on("quit-install", (e, arg) => {
        autoUpdater.quitAndInstall();
    })
    //接收渲染进程消息,开始检查更新
    ipcMain.on("checkForUpdate", (e, arg) => {
        autoUpdater.checkForUpdates();
    })
}
//给渲染进程发送消息
function sendUpdateMessage(text) {
    mainWindow.webContents.send('message', text)
}

3.3.2 在background.js引入handleUpdate.js文件

const { handleUpdate } = require('./handleUpdate') //根据自己路径引入

//检查更新 http://192.168.3.43/dist/   新版本更新包访问路径
handleUpdate(win, "http://192.168.3.43/dist/")

3.3.3 background.js完整代码

'use strict'

import { app, protocol, BrowserWindow } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const {
  handleUpdate
} = require('./handleUpdate') //根据自己路径引入
const isDevelopment = process.env.NODE_ENV !== 'production'
const path = require('path')
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
  { scheme: 'app', privileges: { secure: true, standard: true } }
])

async function createWindow() {
  // Create the browser window.
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
      contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
    }
  })
  win.maximize();//默认打开窗口最大化
  win.show();
  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
    if (!process.env.IS_TEST) win.webContents.openDevTools()
  } else {
    createProtocol('app')
    // Load the index.html when not in development
    win.loadURL('app://./index.html')
  }

  //检查更新 http://192.168.3.43/dist/   新版本更新包访问路径
  handleUpdate(win, "http://192.168.3.43/dist/")
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})
app.on('quit', () => {
  app.quit()
})

app.on('activate', () => {
  // On macOS 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()
})

// 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', async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      await installExtension(VUEJS_DEVTOOLS)
    } catch (e) {
      console.error('Vue Devtools failed to install:', e.toString())
    }
  }
  createWindow()
})

// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
  if (process.platform === 'win32') {
    process.on('message', (data) => {
      if (data === 'graceful-exit') {
        app.quit()
      }
    })
  } else {
    process.on('SIGTERM', () => {
      app.quit()
    })
  }
}

3.3.4在App.vue执行自动更新

每隔10分钟对比服务器上的版本,版本不同执行自动更新

<script>
let ipcRenderer = require("electron").ipcRenderer;
export default {
  components: {
 
  },
  data() {
    return {
     
    };
  },
  created() {},
  unmounted() {
    clearInterval(this.timer);
  },
  mounted() {
    console.log(ipcRenderer);
    let _this = this;
    //新增
    this.timer = setInterval(() => {
      setTimeout(() => {
        console.log('执行定时器');
        ipcRenderer.send("checkForUpdate");
      }, 1);
    }, 600000);

    //接收主进程版本更新消息
    ipcRenderer.on("message", (event, arg) => {
      console.log(arg);
    });
  },
};
</script>

3.4 实现强制安装并运行程序

在handleUpdate.js文件夹中的监听下载完成事件中配置 autoUpdater.quitAndInstall();

// 监听下载完成事件
autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl) {
        sendUpdateMessage({
            cmd: 'update-downloaded',
            message: {
                releaseNotes,
                releaseName,
                releaseDate,
                updateUrl
            }
        })

        //退出并安装更新包
        autoUpdater.quitAndInstall();
    });

在package.json配置

 "scripts": {
    "start": "electron .",
}

 

 编写installer.nsh脚本,实现安装成功之后自动运行程序

将installer.nsh脚本放在vue项目根路径下的build文件,没有的话自己创建

!macro customFinishPage
AutoCloseWindow true
Function StartApp
    ${if} ${isUpdated}
      StrCpy $1 "--updated"
    ${else}
      StrCpy $1 ""
    ${endif}
    ${StdUtils.ExecShellAsUser} $0 "$launchLink" "open" "$1"
FunctionEnd

Function .onInstSuccess
    Call StartApp
FunctionEnd

!macroend

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值