Electron 4 Windows - >电子助推器 - >自动更新:自定义解决方案

时间:2016-04-21 12:48:18

标签: node.js windows auto-update electron squirrel.windows

我正在使用Electron为Windows构建应用。要打包和分发它,请使用electron-builder。 Electron-builder依赖于许多软件包,对于自动更新,它使用Squirrel-windows

我在Windows上与自动更新斗争了3天,最后我提出了一个似乎没有问题的可行解决方案。

我不会'深入了解我尝试过的细节,但失败了。相反,我会在这里发布我已经提出的解决方案。

我与你们分享,看看你是否可以向我指出任何会导致我的系统失败的缺陷,或者,如果真的是一个可靠的解决方案,那就帮助那些正在努力奋斗的人是。由于后一个原因,我发布了比必要更多的代码,希望它能帮助其他人。

逻辑如下:

  • 如果当前可执行文件的路径中的子文件夹fullupdate不存在(请参阅后面的内容,将会澄清),我们连接在线服务器并通过发送当前服务器检查是否有更新app version;
  • 如果没有更新,则不执行任何操作。
  • 如果有更新,我们会指示服务器返回一个json字符串,其中包含我们可以从中下载由.exe生成的electron-builder安装程序的网址。注意:不是.nupkg(服务器代码未提供:-))。
  • 我们下载该文件并将其保存在我们的应用程序当前保存的本地文件夹中的子文件夹fullupdate内。这应该是'#34;安全"由于electron-builder将应用保存在当前用户文件夹AppData中,因此我们不应该有权限问题。
  • 在下载结束时,我们在文件夹update内创建一个新文件fullupdate,以确保下载已成功完成。我们也可以重命名文件,但我更喜欢这种方式。
  • 下次应用程序打开时:
    • 如果文件夹fullupdate存在,我们检查文件update是否存在。如果它不存在,则下载未完成,因此我们删除文件夹fullupdate并再次调用远程服务器以重新开始。
    • 否则,如果文件update存在,我们会启动已下载的.exe文件,并返回true。这将阻止应用程序打开主窗口。很酷的是,更新程序将删除AppData中保存的应用程序的整个旧版本(同时保留本地用户数据)并将其替换为新版本。通过这种方式,我们也将删除文件夹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;
}

0 个答案:

没有答案