vue+electron+electron-updater

本文档详细介绍了如何使用Vue CLI创建一个Electron项目,并集成自动更新功能,通过electron-updater库进行版本检测和下载。同时,展示了如何配置vue.config.js以支持自动更新,以及在主进程中处理更新流程。此外,还涵盖了日志处理,使用electron-log库记录应用日志,并在渲染进程中调用ipcRenderer进行通信。
摘要由CSDN通过智能技术生成

1.先创建vue项目

1.1安装脚手架

npm install -g @vue/cli
# OR
yarn global add @vue/cli

1.2创建项目

vue create electron-demo

2.安装electron (electron版本选择11)

vue add electron-builder

3.安装自动更新插件

npm install electron-updater --save

4.配置vue.config文件

module.exports = {
 pluginOptions: {
    electronBuilder: {
      outputDir: "upms-dist",
      nodeIntegration: true,
      builderOptions: {
        appId: "wltDemo.com", //应用id
        productName: "upms", // 项目名,也是生成的安装文件名,即wyDemo.exe
        copyright: "upms Copyright © 2022", // 版权信息
        // 'files': [
        //     './**/*'
        // ],
        // 'directories': {
        //     'output': './electronPack' // 输出文件路径
        // },
        extraResources:["./src/extraResources/**"],//打包托盘图标
        publish: [
          {
            provider: "generic",
            url: "http://192.168.0.100:8099/electron/",
            // url: "http://127.0.0.1:8099/electron/",
          },
        ],
        win: {
          // win相关配置
          icon: "./src/assets/images/logo.png", // 窗口左上角图标256*256
          requestedExecutionLevel: "requireAdministrator", //获取管理员权限
          target: [
            {
              target: "nsis", // 利用nsis制作安装程序
              arch: [
                "x64", // 64位
                "ia32",
              ],
            },
          ],
        },
        nsis: {
          oneClick: false, // 是否一键安装
          allowElevation: true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
          allowToChangeInstallationDirectory: true, // 允许修改安装目录
          installerIcon: "./favicon.ico", // 安装图标
          uninstallerIcon: "./favicon.ico", // 卸载图标
          installerHeaderIcon: "./favicon.ico", // 安装时头部图标
          createDesktopShortcut: true, // 创建桌面图标
          createStartMenuShortcut: true, // 创建开始菜单图标
          shortcutName: "upms", // 桌面图标名称(项目名称)
        }
      },
    },
  },
}

5.新建electron-update.js文件

import { autoUpdater, NoOpLogger } from "electron-updater";
import config from ".././package.json";
import { ipcMain, app, dialog } from "electron";

const logger = require("electron-log");
let mainWindow = null;
autoUpdater.autoDownload = false;
let canQuit = false;
let version=''

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

  autoUpdater.setFeedURL(feedUrl);
  autoUpdater.checkForUpdates();

  //监听升级失败事件
  autoUpdater.on("error", function (error) {
    sendUpdateMessage({
      cmd: "error",
      message: error,
    });
    logger.error("监听系统升级事件失败");
  });

  //监听开始检测更新事件
  autoUpdater.on("checking-for-update", function (message) {
    sendUpdateMessage({
      cmd: "checking-for-update",
      message: message,
    });
    console.log("检查");
    logger.info("开始监听系统升级事件");
  });
  //监听没有可用更新事件
  autoUpdater.on("update-not-available", function (message) {
    sendUpdateMessage({
      cmd: "update-not-available",
      message: message,
    });
    logger.info("没有发现新版本");
  });
  //监听发现可用更新事件
  autoUpdater.on("update-available", function (message) {
   version=message.version
    sendUpdateMessage({
      cmd: "update-available",
      message: message,
    });
    autoUpdater.autoDownload = true;
    logger.info("发现有新版本");
  });

  // 更新下载进度事件
  autoUpdater.on("download-progress", function (progressObj) {
    //事件没触发可能更新包已下载
    sendUpdateMessage({
      cmd: "download-progress",
      message: progressObj,
    });
    logger.info("更新下载进度...");
  });

  autoUpdater.on("close", (event) => {
    if (!canQuit) {
      mainWindow.hide();
      mainWindow.setSkipTaskbar(true);
      event.preventDefault();
    }
  });

  //监听下载完成事件
  autoUpdater.on(
    "update-downloaded",
    function (event, releaseNotes, releaseName, releaseDate, updateUrl) {
      logger.info("下载包成功");
      sendUpdateMessage({
        cmd: "update-downloaded",
        message: {
          releaseNotes,
          releaseName,
          releaseDate,
          updateUrl,
        },
      });
      // //退出并安装更新包
      // if (process.platform !== "darwin") {
      //   canQuit = true;
      //   // autoUpdater.quitAndInstall();
      //   setImmediate(() => autoUpdater.quitAndInstall(true, true));
      //   logger.info('下载完成,退出并且安装更新包')
      // }
      app.whenReady().then(() => {
        logger.info("下载提示");
        let clickId = dialog.showMessageBoxSync({
          type: "info",
          title: "升级提示",
          essage: `已为你升级到最新版V${version},是否立即体验`,
          buttons: ["立即体验", "稍后体验"],
          cancelId: 1,
        });
        if (clickId === 0) {
          logger.info("下载完成,退出并且安装更新包");
          canQuit = true;
          setImmediate(() => autoUpdater.quitAndInstall(true, true));
        } else {
          sendUpdateMessage({
            cmd: "update-await",
            message: "稍后重启",
          });
        }
      });
    }
  );

  //接收渲染进程消息,开始检查更新
  // ipcMain.on("checkForUpdate", (e, arg) => {
  //   //执行自动更新检查
  //   // sendUpdateMessage({cmd:'checkForUpdate',message:arg})
  //   if (arg) {
  //     autoUpdater.autoDownload = true;
  //   }
  //   console.log(e,arg,'hhhh');
  //   autoUpdater.checkForUpdates();
  // });
}
//给渲染进程发送消息
function sendUpdateMessage(text) {
  mainWindow.webContents.send("message", text);
}

6.在主进程background中引入

"use strict";

import {
  app,
  protocol,
  BrowserWindow,
  BrowserView,
  Tray,
  Menu,
  ipcMain,
  webContents,
  CommandLine,
} from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
const fs = require("fs");
import path from "path";
import { event } from "jquery";
import { updateHandle } from "@/electron-update.js";
const gotTheLock = app.requestSingleInstanceLock();
const isDevelopment = process.env.NODE_ENV !== "production";
import logger from "@/logFile"; //引入封装好的代码
var win;
let willQuitApp = false;
const { crashReporter } = require("electron");
app.setPath("crashDumps", "D:/crashe_log"); //在启动崩溃报告器之前覆盖该目录Crashpad

protocol.registerSchemesAsPrivileged([
  { scheme: "app", privileges: { secure: true, standard: true } },
]);
logger.info("启用日志");
async function createWindow() {
  // Create the browser window.
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      //false关闭web权限检查,允许跨域
      webSecurity: false,
      nodeIntegration: true,
      nodeIntegrationInWorker: false, // 是否在Web工作器中启用了Node集成
      // preload: path.join(__dirname, "../src/preload.js"),
      preload: path.resolve(__dirname, "../src/extraResources/preload.js"),
      contextIsolation: false,
      show: false,
    },
  });
  let view = new BrowserView();
  win.setBrowserView(view);
  view.setBounds({ x: 0, y: 0, width: 500, height: 500 });

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    await view.webContents.loadURL(
      process.env.WEBPACK_DEV_SERVER_URL + "/loading.html"
    );
    await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
    if (!process.env.IS_TEST) win.webContents.openDevTools();
  } else {
    view.webContents.loadURL("app://./loading.html");
    createProtocol("app");
    win.loadURL("app://./index.html");
  }

  view.webContents.on("dom-ready", () => {
    logger.info("开启加载页面");
    win.show();
  });
  ipcMain.on("stop-loading-main", () => {
    logger.info("关闭加载页面");
    win.removeBrowserView(view);
  });

  win.on("close", (e) => {
    if (willQuitApp) {
      win = null;
    } else {
      e.preventDefault(); //阻止窗口的关闭事件
      win.hide();
    }
  });

  win.on("ready-to-show", () => {
    // win.maximize()//窗口最大化
    win.show();
  });

  updateHandle(win, "http://192.168.0.100:8099/electron/");
}

app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit();
  }
});

app.on("will-finish-launching", () => {
  //应用启动
  crashReporter.start({
    productName: "crashDumps",
    companyName: "crashDumps",
    // submitURL: "http://192.168.0.100:8099/crash",
    autoSubmit: true,
    uploadToServer: true, //将崩溃报告发送给服务器
    compress: true, //崩溃报告将压缩并上传,使用带有 Content-Encoding: gzip 的头部
  });
});

app.on("activate", () => {
  // process.crash();
  if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
app.on("before-quit", () => {
  willQuitApp = true;
  win.close();
});
if (!gotTheLock) {
  app.quit();
} else {
  app.on("second-instance", (event) => {
    if (win.isMinimized()) win.restore();
    win.show();
  });
  let appTray = null;
  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();
    // Menu.setApplicationMenu(null) // 隐藏菜单栏
    appTray = new Tray(
      path.resolve(__dirname, "../src/extraResources/logo.png")
    );
    appTray.on("click", () => {
      console.log("click");
      win.show();
    });
    appTray.on("right-click", () => {
      let contextMenu = Menu.buildFromTemplate([
        {
          label: "退出",
          click: app.quit,
        },
      ]);
      appTray.popUpContextMenu(contextMenu);
    });
    appTray.setToolTip("平台");
  });
}

if (isDevelopment) {
  if (process.platform === "win32") {
    process.on("message", (data) => {
      if (data === "graceful-exit") {
        app.quit();
      }
    });
  } else {
    process.on("SIGTERM", () => {
      app.quit();
    });
  }
}

//记录日志
ipcMain.handle("log", async (event, arg) => {
  //与渲染进程通信
  return new Promise((resolve, reject) => {
    logger.info(arg);
  });
});

process.on("uncaughtException", function (error) {
  logger.info(error, "主进程异常");
  // 上报异常

  // 异常日志
});

7.APP.vue中告知主进程关闭预加载页面

  beforeCreate() {
    window.ipcRenderer.send("stop-loading-main");
  }

8.预加载preload.js文件

const electron = require('electron');
window.ipcRenderer = require('electron').ipcRenderer;

后面渲染进程调用ipcRenderer ,通过window.ipcRenderer调用即可 无需从electron引入
9.logFile.js处理日志文件

import logger from 'electron-log'
import {app} from 'electron'
 
logger.transports.file.level = 'debug'
logger.transports.file.maxSize = 1002430 // 10M
logger.transports.file.format = '[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}]{scope} {text}'
let date = new Date()
date = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate()
// logger.transports.file.file = app.getPath('userData') + '\\electron_log\\app\\' + date + '.log'
// 返回位置为日志位置 没有文件夹会自动创建
logger.transports.file.resolvePath = () =>  'D:electron_log\\' + date + '.log'; 

 
export default {
  info (param) {
    logger.info(param)
  },                   
  warn (param) {
    logger.warn(param)
  },
  error (param) {
    logger.error(param)
  },
  debug (param) {
    logger.debug(param) 
  },
  verbose (param) {
    logger.verbose(param)
  },
  silly (param) {
    logger.silly(param)
  }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
文件目录
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值