电子4 Windows – >电子build设者 – >自动更新:自定义解决scheme

我正在使用Electron构buildWindows应用程序。 为了打包和分发,我正在使用电子生成器 。 电子build设者依赖于许多包,而自动更新它使用松鼠窗 。

我一直在Windows上自动更新3天,最后我提出了一个似乎没有问题的工作解决scheme。

我不会去详细介绍我所尝试过的,并且失败了。 相反,我会在这里发布我提出的解决scheme。

我会和你们分享一下,看看你们是否可以向我指出任何会使我的系统失败的缺陷,或者如果这确实是一个可靠的解决scheme,那就帮助那些正在挣扎的人。 由于后一个原因,我发布了一些比所需要的更多的代码,希望能够帮助其他人。

逻辑如下:

  • 如果当前可执行文件的path中的子文件夹fullupdate不存在(请参阅后面的说明),我们连接在线服务器并通过发送当前应用程序版本检查是否有更新;
  • 如果没有更新,什么也不要做。
  • 如果有更新,我们指示服务器返回一个包含url的jsonstring,我们可以从中下载electron-builder生成的.exe安装程序。 注意:不是.nupkg (服务器代码未提供:-) )。
  • 我们下载文件并将其保存在我们的应用程序当前保存的本地文件夹中的子文件夹fullupdate中。 这应该是“安全”的,因为electron-builder将应用程序保存在当前用户文件夹AppData ,所以我们不应该有权限问题。
  • 在下载结束时,我们在fullupdate文件夹内创build一个新的文件update ,以确保下载成功完成。 我们也可以重命名文件,但我更喜欢这种方式。
  • 下次打开应用程序时:
    • 如果文件夹fullupdate存在,我们检查文件update存在。 如果它不存在,下载没有完成,所以我们删除文件夹fullupdate ,再次调用远程服务器重新开始。
    • 否则,如果文件update存在,我们启动我们下载的.exe文件,并返回true。 这将阻止应用程序打开主窗口。 很酷的事情是,更新程序将删除保存在AppData中的应用程序的旧版本(同时保留本地用户数据),并将其replace为新版本。 这样我们也将摆脱fullupdate文件夹。

现在代码:

 // we want to run this only on windows var handleStartupEvent = function() { if (process.platform !== 'win32') { return false; } ///////////////// // MANUAL UPDATER ///////////////// var appFolder = 'app-' + appVersion; var pathApp = path.dirname(process.execPath); var pathUpdate = pathApp + '\\fullupdate'; var checkupdateurl = 'https://api.mysite.com/getjson/' + appVersion.split('.').join('-'); function checkIfDownloaded(){ if (!fs.existsSync(pathUpdate)) checkUpdate(); else return checkIfInstallLocal(); } function checkIfInstallLocal(){ if(fileExists('fullupdate\\update')) return installLocal(); else { deleteFolderRecursive(pathUpdate); checkUpdate(); } } function installLocal(){ cp.exec('fullupdate\\Update.exe', function( error, stdout, stderr){ if ( error != null ) { console.log(stderr); } }); return true; } // from http://www.geedew.com/remove-a-directory-that-is-not-empty-in-nodejs/ var deleteFolderRecursive = function(path) { if( fs.existsSync(path) ) { fs.readdirSync(path).forEach(function(file,index){ var curPath = path + "/" + file; if(fs.lstatSync(curPath).isDirectory()) deleteFolderRecursive(curPath); else fs.unlinkSync(curPath); }); fs.rmdirSync(path); } }; // from http://stackoverflow.com/questions/4482686/check-synchronously-if-file-directory-exists-in-node-js function fileExists(path) { try { return fs.statSync(path).isFile(); } catch (e) { if (e.code == 'ENOENT') { // no such file or directory. File really does not exist return false; } throw e; // something else went wrong, we don't have rights, ... } } function checkUpdate(){ https.get('https://api.mysite.com/getjson/' + app.getVersion().split('.').join('-'), (res) => { res.setEncoding('utf8'); res.on('data', function(chunk) { if(chunk) thereIsUpdate(chunk); }); }).on('error', (e) => { console.log(e); }); } function thereIsUpdate(chunk){ var data = JSON.parse(chunk); if(data && data.url) getNewUpdate(data.urlsetup); } function getNewUpdate(url){ fs.mkdirSync(pathUpdate); var file = fs.createWriteStream(pathUpdate + '/Update.exe'); var responseSent = false; // flag to make sure that response is sent only once. var request = https.get(url, function(response) { response.pipe(file); file.on('finish', () =>{ file.close(() => { if(responseSent) return; responseSent = true; }); fs.closeSync(fs.openSync(pathUpdate + '/update', 'w')); }); }); } if(checkIfDownloaded()) return true; ///////////////////////// // SQUIRREL EVENTS HANDLER ////////////////////////// // see http://stackoverflow.com/questions/30105150/handle-squirrels-event-on-an-electron-app }; // here we call the function. It is before the opening of the window, so that we prevent the opening if we are updating, or if there is a Squirrel event going on (see SO question, link above) if (handleStartupEvent()) { return; }