<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          研究Electron自動(dòng)更新 系列三【近8k字】

          共 10643字,需瀏覽 22分鐘

           ·

          2021-03-06 15:33

          這是繼《研究 Electron 自動(dòng)更新》系列的最后一篇,感謝大家的耐心閱讀。

          系列一從自動(dòng)更新的方案深入地講解了其中的原理,另外還講解了兩種打包方式。

          系列二列舉了開發(fā)中出現(xiàn)的三個(gè)問題,分別是“Can not find Squirrel”、“安裝目錄中packages文件夾和Update.exe程序找不到”和“Error: spawn UNKNOWN”,從不同角度分析并且作了解答。

          本文就繼續(xù)系列二,再講講遇到的其他問題。

          開發(fā)中存在的問題

          (四) Error Downloading Update: Command failed: 4294967295

          1. 背景

          自動(dòng)更新過程中出現(xiàn)“Error Downloading Update: Command failed: 4294967295”的報(bào)錯(cuò),這個(gè) error 和系列二中的問題3Error: spawn UNKNOWN” 很類似,因?yàn)檫@個(gè)問題很常見,所以我要挑出來講。

          2. 原因分析

          這個(gè)問題在 Squirrel.Windowsissueshttps://GitHub.com/Squirrel/Squirrel.Windows/issues/833)中也有, 其中的回答繞不過一點(diǎn):程序的錯(cuò)誤,遠(yuǎn)程發(fā)布文件是空的或損壞影響我們的更新。

          3. 解決方式

          對(duì)于開發(fā)者來說,我需要重新上傳新的安裝程序。還有可能是更新服務(wù)器提供的下載 nupkgurl 出錯(cuò),這個(gè)需要通過  SquirrelSetup.log 去仔細(xì)檢查,不難的。

          對(duì)于用戶來說,可能需要先卸載后重新安裝新的版本。

          (五) 更新后,老版本沒有被替換

          1. 背景

          如果當(dāng)前電腦上的應(yīng)用版本是 0.0.1,服務(wù)器上最新是 0.0.2。自動(dòng)更新完成后,多出來一個(gè)新版本的目錄 app-0.0.2,但是沒有覆蓋 xxx 項(xiàng)目,桌面快捷方式打開的還是 xxx 項(xiàng)目里的舊版本。

          究其原因,歸咎于 nsis 沒有集成 updateManage 機(jī)制。系列一和二已經(jīng)描述過,就不再贅述。


          目錄

          圖 7 安裝目錄

          2. 解決方案

          1. 向服務(wù)器每隔一段時(shí)間發(fā)送當(dāng)前版本的請(qǐng)求,詢問其是否有新版本的應(yīng)用(setFeedURLcheckForUpdates 方法實(shí)現(xiàn));
          2. 當(dāng)有更新進(jìn)入 error、checking-for-update、update-availableupdate-not-available 這些鉤子方法時(shí),寫入日志;
          3. 更新進(jìn)入 update-downloaded,提示用戶更新完成,手動(dòng)重啟。然后,啟動(dòng)一個(gè)子進(jìn)程去執(zhí)行 bat 腳本,替換安裝目錄下面的舊版本。

          xxx 項(xiàng)目的更新代碼,見 update.js

          import {autoUpdater} from 'electron'
          // 服務(wù)器地址
          const server = 'XXXXXXX'
          const url = `${server}/update/${process.platform}/${app.getVersion()}/stable`
          logger.info(`url:${url}`)
          // 設(shè)置請(qǐng)求地址
          autoUpdater.setFeedURL({
            url
          })
          logger.info(`process.ExecPath:${process.ExecPath}`)
          // 檢查更新
          setInterval(() => {
            autoUpdater.checkForUpdates()
            logger.info('checkForUpdates')
          }, 900000)

          const appName = '應(yīng)用更新'
          const message = {
            error'檢查更新出錯(cuò)',
            checking'正在檢查更新……',
            updateAva'下載更新包成功',
            updateNotAva'現(xiàn)在使用的就是最新版本,不用更新',
            downloaded'更新完成,請(qǐng)手動(dòng)重啟'
          }
          autoUpdater.on('error', error => {
            logger.error('There was a problem updating the application')
            logger.error(error)
          })
          .on('checking-for-update'function ({
              logger.info('當(dāng)開始檢查更新的時(shí)候觸發(fā)')
            })
            .on('update-available'function ({
              logger.info('當(dāng)有可用更新時(shí)發(fā)出,更新會(huì)自動(dòng)下載')
            })
            .on('update-not-available'function ({
              logger.info('暫無更新')
            })
          autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
            logger.info('update-downloaded')
            logger.info(`releaseNotes:${releaseNotes}`)
            logger.info(`releaseName:${releaseName}`)

            dialog.showMessageBox({
              type'info',
              buttons: ['確定'],
              title: appName,
              message: process.platform === 'win32' ? releaseNotes : releaseName,
              detail: message.downloaded
            }).then((returnValue) => {
              if (returnValue.response === 0) {
                fs.writeFile('../releaseName.txt', releaseName, (err) => {
                  if (err) {
                    logger.error(err)
                    throw err
                  } else {
                    var ls
                    ls = childProcess.spawn('libs/Windows/adb/adb', ['kill-server'])
                    ls.stdout.on('data'function (data{
                      logger.info('stdout: ' + data)
                    })
                    ls.stderr.on('data'function (data{
                      logger.error('stderr: ' + data)
                    })
                    ls.on('exit'function (code{
                      logger.info('目錄替換程序開始運(yùn)行')
                      // 地址
                      const a = process.cwd()
                      logger.info('a ' + a)
                      const arr = a.split('\\')
                      logger.info('arr ' + arr)
                      const pre = a.slice(0, -arr[arr.length - 1].length)
                      logger.info('pre' + pre)
                      process.chdir(pre)
                      childProcess.Exec(`start /min  "" "${pre}replace.bat" ${releaseName}`)
                      setTimeout(() => {
                        logger.info('xxx項(xiàng)目退出')
                        app.quit()
                      }, 1000)
                    })
                  }
                })
              }
            })
          })

          xxx 項(xiàng)目新版本替換舊版本的腳本,見 Replace.bat

          chcp 65001
          echo **更新即將完成,請(qǐng)勿關(guān)閉窗口!** >> replace.log
          ping -n 5 127.0.0.1 >> replace.log
          COPY ".\xxx項(xiàng)目\Uninstall xxx項(xiàng)目.Exe" app-%1 >> replace.log
          COPY ".\xxx項(xiàng)目\uninstallerIcon.ico" app-%1 >> replace.log
          RD /q /s ".\xxx項(xiàng)目" >> replace.log
          ren app-%1 "xxx項(xiàng)目" >> replace.log
          del "xxx項(xiàng)目.Exe" >> replace.log
          exit

          (六) Update.exe之外的操作無日志

          1. 背景

          主進(jìn)程中加入 console,僅僅打印在終端上,并不能持久化日志。

          更新過程中產(chǎn)生的日志都存儲(chǔ)在 SquirrelSetup.log 中,但是僅僅只是 Update.exe 產(chǎn)出的日志??墒呛芏嗖襟E需要輸出更多的日志。自動(dòng)化工具中的部分更新日志采用 log4js 方案,將不同的日志類型輸出在不同文件中。

          2. 解決方案

          xxx 項(xiàng)目的日志配置,見 log4js.js

          const log4js = require('log4js')
          const programName = 'xxx項(xiàng)目'
          log4js.configure({
            appenders: {
              console: { // 記錄器1:輸出到控制臺(tái)
                type'console'
              },
              log_file: { // 記錄器2:輸出到文件
                type'file',
                filename`./logs/${programName}.log`
                maxLogSize20971520
                backups3
                encoding'utf-8' 
              },
              data_file: { // :記錄器3:輸出到日期文件
                type'dateFile',
                filename`./logs/${programName}`,  
                alwaysIncludePatterntrue,  
                daysToKeep7
                pattern'yyyy-MM-dd-hh.log'
                encoding'utf-8' 
              },
              error_file: { // :記錄器4:輸出到error log
                type'dateFile',
                filename`./logs/${programName}_error`
                alwaysIncludePatterntrue
                daysToKeep7
              
                pattern'yyyy-MM-dd-hh.log'
                encoding'utf-8' 
              }
            },
            categories: {
              default: {
                appenders: ['data_file''console''log_file'],
                level'info'
              }, // 默認(rèn)log類型,輸出到控制臺(tái) log文件 log日期文件 且登記大于info即可
              production: {
                appenders: ['data_file'],
                level'warn'
              }, // 生產(chǎn)環(huán)境 log類型 只輸出到按日期命名的文件,且只輸出警告以上的log
              console: {
                appenders: ['console'],
                level'debug'
              }, // 開發(fā)環(huán)境  輸出到控制臺(tái)
              debug: {
                appenders: ['console''log_file'],
                level'debug'
              }, // 調(diào)試環(huán)境 輸出到log文件和控制臺(tái)
              error_log: {
                appenders: ['error_file'],
                level'error'
              } // error 等級(jí)log 單獨(dú)輸出到error文件中 任何環(huán)境的errorlog 將都以日期文件單獨(dú)記錄
            }
          })

          module.exports = log4js

          總結(jié)

          解決的方式可能會(huì)很多,但是需要采用一種適合自己的方式鉆研到底,堅(jiān)持不懈,就一定能得到收獲。

          文中介紹了當(dāng)前存在的問題、自動(dòng)更新的方案、打包的兩種方式和開發(fā)中存在的問題。其中,xxx 項(xiàng)目采用的是 squirrel.windows 的更新機(jī)制和 nsis 的自定義安裝策略。

          通過 electron-builder 將兩者配置后,產(chǎn)出不同的安裝程序 setup.exe 和更新程序 nupkg。然后將 nsissetup.exesquirrel.windows 中的 nupkg 上傳到 electron-release-server 中。利用 electron-release-server 定時(shí)檢查策略,對(duì)比本地版本和線上版本,自動(dòng)下載依賴和程序,進(jìn)行更新并且替換,做到用戶無感知,操作不繁瑣。

          開發(fā)中遇到問題其實(shí)不止這些,由于篇幅問題,所以我總結(jié)了一部分常見的問題。

          最后,希望大家一定要點(diǎn)贊三連。

          可以閱讀我的其他文章,見blog地址

          一個(gè)學(xué)習(xí)編程技術(shù)的公眾號(hào)。常常推送高質(zhì)量的優(yōu)秀博文、開源項(xiàng)目、實(shí)用工具、面試技巧、編程學(xué)習(xí)資源等等。目標(biāo)是做到個(gè)人技術(shù)與公眾號(hào)一起成長(zhǎng)。歡迎大家關(guān)注,一起進(jìn)步,走向全棧大佬的修煉之路

          瀏覽 62
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  a在线视频中文字幕 | 色婷婷www | 无码人妻精品一区二区蜜桃在线看 | www.黄色大片 | 大鸡巴视频在线观看免费 |