LordBingShipley
LordBingShipley

Reputation: 135

Electron - Invalid package on unzip

For around 3 weeks I've been working on an Electron app and finally decided to get around to adding update checking. For my research, the standard way to do this in Electron (using Squirrel) requires the user to physically install the application onto their computer. I would rather not do this, and keep everything as portable as possible. I then decided to try making my own update script by having the program download the update.zip, and extract it to overwrite the existing files. This works well, up until the very end. At the very end of the extraction, I receive a Invalid package error, and the actual app.asar file is missing, rendering the application useless.

I am using this to download and extract the updates:

function downloadFile(url, target, fileName, cb) { // Downloads
    var req = request({
        method: 'GET',
        uri: url
    });

    var out = fs.createWriteStream(target+'/'+fileName);
    req.pipe(out);

    req.on('end', function() {
        unzip(target+'/'+fileName, target, function() {
            if (cb) {
                cb();
            }
        });
    });
}
function unzip(file, target, cb) { // Unzips

    var out = fs.createReadStream(file);
    out.pipe(unzipper.Extract({ path: target })).on('finish', function () {
        dialog.showMessageBox({
            type: 'question',
            message: 'Finished extracting to `'+target+'`'
        });

        if (cb) {
            cb();
        }
    });
}

And call it with:

downloadFile('http://example.com/update.zip', path.join(__dirname, './'), 'update.zip', function() { // http://example.com/update.zip is not the real source
    app.relaunch();
    app.quit();
});

And I use the unzipper NPM package (https://www.npmjs.com/package/unzipper).

The code works perfectly for all other zips, but it fails when trying to extract a zip containing an Electron app.

Anything I'm doing wrong, or maybe a different package that properly supports extracting zips with .asar files?

Edit 1 I just found https://www.npmjs.com/package/electron-basic-updater, which does not throw the same JavaScript error however it still does not extract the .asar files correctly, and will throw it's own error. Since the .asar is still missing, the app is still useless after the "update"

Upvotes: 5

Views: 3734

Answers (2)

Lasha
Lasha

Reputation: 625

This subject is still not clearly explained even today. I encountered an issue with the extract-zip npm extractor. When I tried to decompress a folder from a zip file that contained an asar file, it failed and displayed an error message stating that it couldn't extract the asar file. I was quite confused by this. However, after some research, I discovered that adding the line process.noAsar = true before any failing operation would resolve the problem. Here's an example in my case:

async function unzipFunc(pathObject) {
    try {
        process.noAsar = true
        await extract(path.resolve(pathObject?.unzipSourcePath), {dir: path.resolve(pathObject?.unzipDestinationPath)})
        console.log('Extraction complete')
    } catch (err) {
        console.log("Extraction Error: ", err)
    }
}

As I understand this flag disables the asar module's override of the fs module in Node.js, allowing the extraction process to proceed without conflicts. It tells the asar module not to intercept file operations within the Node.js environment.

By setting process.noAsar = true, we ensure that the fs module behaves normally when extracting the asar file... Hope it will help.

Upvotes: 2

Konstantin
Konstantin

Reputation: 340

Thanks to your link to electron-basic-updater, I have found this issue mentioned there: https://github.com/TamkeenLMS/electron-basic-updater/issues/4.

They refer to the issue in the electron app: https://github.com/electron/electron/issues/9304.

Finally, in the end of the second topic there's a solution:

This is due to the electron fs module treating asar files as directories rather than files. To make the unzip process work you need to do one of two things:

  • Set process.noAsar = true
  • Use original-fs instead of fs

I have seen the people working with original-fs. But it looked like a big trouble to me.

So I tried setting process.noAsar = true (and then process.noAsar = false after unzipping) - and that worked like a charm.

Upvotes: 2

Related Questions