前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Electron实现应用更新的坑及路径的最佳实践

Electron实现应用更新的坑及路径的最佳实践

作者头像
码客说
发布2022-03-09 09:08:00
1.2K0
发布2022-03-09 09:08:00
举报
文章被收录于专栏:码客

前言

应用内更新的逻辑是,应用内检测受否需要更新,如果需要更新,安装包下载到本地后,进行打开安装,同时关闭当前应用。

旧版本的API为

代码语言:javascript
复制
const {shell} = window.require("electron");
shell.openItem(filepath);

旧版本是没有问题的。

新版本变更为

代码语言:javascript
复制
const {shell} = window.require("electron");
shell.openPath(filepath);

但是这样就出现问题了,新版本打开是在子进程中,安装应用安装包时,应用进程是必须要关闭,如果应用进程关闭,安装包对应的子进程也会关闭,导致安装终止。

node-cmd

所以只能更换一种方式

代码语言:javascript
复制
npm install node-cmd -s

在Electron中

代码语言:javascript
复制
const cmd = window.require('node-cmd');
cmd.run('start "" "' + filepath + '"');

注意启动应用应该这样

代码语言:javascript
复制
start "" "D:\Project\myapp.exe"

注意

  1. 路径要添加双引号,否则路径中有空格就无法打开应用。
  2. start命令后要添加"",否则打不开应用,第一个参数会被当做标题,第二个才是文件路径。

node-cmd简介

node-cmd模块中主要有run和get两类命令,其中run是执行cmd命令,get命令除了异步执行cmd命令外,在执行完毕后还会执行回调函数,返回命令行窗口的输出。

代码语言:javascript
复制
var cmd = require('node-cmd');

cmd.run('touch example.created.file');

cmd.get(
  'ls',
  function(data){
    console.log('the current dir contains these files :\n\n',data)
  }
);

完整示例

完整的下载应用代码示例:

渲染进程中

代码语言:javascript
复制
const path = window.require("path");
const {app} = window.require("electron").remote;
const cmd = window.require('node-cmd');

async update_app_action() {
  let versionpath = this.version_obj["versionpath"];
  let versioncode = this.version_obj["versioncode"];
  let file_url = `${filedownloadUrl}${versionpath}`;
  let temp_path = remote.getGlobal("sharedObject").temp_path;
  try {
    if (!fs.existsSync(temp_path)) {
      fs.mkdirSync(temp_path, {recursive: true});
    }
  } catch (e) {
  }
  let filename = versioncode + "_" + versionpath.substring(versionpath.lastIndexOf("/") + 1);
  let temp_filename = "temp_" + filename;

  const filepath = path.join(
    temp_path,
    filename
  );

  const temp_filepath = path.join(
    temp_path,
    temp_filename
  );
  //文件存在直接打开
  if (fs.existsSync(filepath)) {
    cmd.run('start "" "' + filepath + '"');
  } else {
    // 不存在下载后打开
    if (fs.existsSync(temp_filepath)) {
      fs.unlinkSync(temp_filepath);
    }
    this.version_down = true;
    try {
      await this.download_file(file_url, temp_filepath);
      this.version_down = false;
      this.version_flag = false;
      fs.renameSync(temp_filepath, filepath)
      cmd.run('start "" "' + filepath + '"');
    } catch (e) {
      console.info("更新失败!")
    }
  }
}

download_file(file_url, path) {
  return new Promise((resolve, reject)=>{
    const url = require("url");
    const {http, https} = require("follow-redirects");
    let myhttp = http;
    if (file_url.indexOf("https:") !== -1) {
      myhttp = https;
    }
    const options = url.parse(file_url);
    let filldiv = document.getElementById("filldiv");
    try {
      const request = myhttp.request(options, (response)=>{
        const file_length = response.headers["content-length"];
        let downd_length = 0;
        let m_stream = fs.createWriteStream(path);
        response.on("data", (chunk)=>{
          downd_length += chunk.length;
          let down_progress = Math.ceil((downd_length * 100) / file_length);
          this.version_progress = down_progress;
          filldiv.style.width = down_progress * 4 + "px";
          //filldiv添加一个随机背景颜色
          filldiv.style.background = "#33C5B3";
          m_stream.write(chunk);
        });
        response.on("end", function() {
          m_stream.end();
          m_stream.on('close', ()=>{
            resolve(path);
          })
        });
      });
      request.end();
    } catch (e) {
      reject("下载失败!");
    }
  })
},

Electron路径最佳实践

如果渲染进程太多,不建议在渲染进程中获取路径,建议在主进程中设置。

主进程

代码语言:javascript
复制
const {app} = require("electron");
const path = require("path");
const fs = require("fs");

global.sharedObject = {
  temp_path: "",
}

let basepath = "";

try {
  basepath = app.getPath("downloads");
} catch (e) {
  basepath = path.dirname(app.getPath("exe"));
}

if (/.*[\u4e00-\u9fa5 ]+.*$/.test(basepath)) {
  basepath = "C:\\";
}

let temp_path = path.join(
  basepath,
  "school_live_temp"
)

try {
  if (!fs.existsSync(temp_path)) {
    fs.mkdirSync(temp_path, {recursive: true});
  }
} catch (e) {
}

console.info("temp_path", temp_path);
global.sharedObject.temp_path = temp_path;

注意

在有些电脑上竟然无法使用app.getPath("downloads")获取路径,所以这里进行异常捕获。 有些电脑用户名是中文,而某些SDK不支持路径中包含中文和空格,这里也做了判断。

渲染进程

代码语言:javascript
复制
const remote = window.require("electron").remote;
let temp_path = remote.getGlobal("sharedObject").temp_path;
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • node-cmd
    • node-cmd简介
    • 完整示例
    • Electron路径最佳实践
    相关产品与服务
    命令行工具
    腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档