我正在使用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;
}