Open glk-hll opened 3 years ago
So I found one workaround on my environment(Mac OS) "chmod +x 'path of 7za'" which gets things working but I wouldn't call a perfect solution
Anyone found a better way of getting things working
This error says that it cannot execute that particular file because apparently it doesn't exist. The problem here is that app.asar
is a special archive type and spawn cannot execute files that are stored there.
One solution for this is to "unpack" 7zip-bin
during Electron packaging process and then reference it from that "unpacked" folder.
For example if you use electron-builder, this property in config can be used
{
"asarUnpack": ["node_modules/7zip-bin"]
}
This tells electron-builder to move these files outside that app.asar
archive and into app.asar.unpacked
, which is just a regular folder. Then when requiring path to 7zip-bin
, some transformation on the required path can be performed.
const asarToAsarUnpacked = (path) => {
if (!/app\.asar\.unpacked/.test(path)) {
const pathUnpacked = path.replace(/app\.asar/, "app.asar.unpacked");
if (existsSync(pathUnpacked)) {
path = pathUnpacked;
}
}
return path;
};
const sevenZipBinPath = asarToAsarUnpacked(require("7zip-bin").path7za);
Hopefully this helps someone. I got to this solution through various posts, digging through some code for some open source Electron projects and who knows what else 😄
I know this worked for me in the past, but unfortunately it stopped working on one project where I use this technique. Not sure why it happened, but I guess I'm just overlooking something I did with dependency/environment updates in the recent past.
I've managed to resolve my issue by kinda manually pointing to the appropriate binary file.
const getSevenZipBinPath = () => {
let sevenZipModuleRootPath = "";
if (App.isDevelopmentMode()) {
// In development this require.resolve() call resolves to proper path to 7zip-bin entry file, but accessing ".path7za" exported property gives wrong path
const sevenZipModulePath = require.resolve("7zip-bin");
// Previous line resolves to "index.js" entry path so we just go back one path fragment to get to the root of the 7zip-bin module folder
sevenZipModuleRootPath = path.resolve(sevenZipModulePath, "..");
} else {
// In production we can just access resources path and construct the rest of the path from there
sevenZipModuleRootPath = path.join(process.resourcesPath, "app.asar.unpacked", "node_modules", "7zip-bin");
}
return path.join(sevenZipModuleRootPath, "win", process.arch, "7za.exe");
};
I do have to worry about Windows only so there is no code here to handle other operating systems, but it wouldn't be hard to add that if necessary.
Not sure what caused issues for me, but googling some stuff it seems like it might be a Webpack thing where Webpack is kinda replacing __dirname or require() calls and thus not resolving to what I would expect. That is possible since I've updated all project dependencies recently and this probably triggered all of this somewhere under the hood.