electron-userland / electron-builder

A complete solution to package and build a ready for distribution Electron app with “auto update” support out of the box
https://www.electron.build
MIT License
13.62k stars 1.74k forks source link

Windows Store Submit Issue #3768

Closed idoodler closed 5 years ago

idoodler commented 5 years ago

I currently do have a Cordova based app in the Windows Store, this Cordova app should be updated to an Electron Application.

Everything works fine, however I am not able to submit the Electron application to the Windows Store.

The following error is been presented: A previous submission for this app was released with a Windows 10 .msixbundle or .appxbundle. Subsequent submissions must continue to contain a Windows 10 .msixbundle or .appxbundle.

How am I supposed to fix this issue, any advice?

idoodler commented 5 years ago

The issue has been resolved via Microsoft Support. It is somehow mandatory to keep submit an appxbundle if your previous application was one.

An appxbundle can easily be bundled, just follow this documentation.

It would be a welcome feature to allow be able to directly build appxbundle files with electron-builder

develar commented 5 years ago

Moved to backlog to keep issue list clear. Pull request or donation (discuss in prior) welcome.

idoodler commented 4 years ago

I just solved this issue with a simple hook that utilizes electron-builds own winCodeSign cache which is automatically downloaded if needed in the building steps before this hook is executed.

Note:

var path = require("path"),
    fs = require("fs"),
    glob = require("glob"),
    childProcess = require('child_process');

exports.default = function(buildResult) {
    buildResult.artifactPaths.forEach(function(appxPath) {
        if (appxPath.endsWith(".appx")) {
            convertAppx2AppxBundle(appxPath);
        }
    });
};

/**
 * Converts a Unix Path to a Windows conforming path by replacing any "/" with "\"
 * @return {string}
 */
String.prototype.windowsify = function windowsify() {
    return this.replace(/\//g, "\\");
}

/**
 * Converts the given appx to an appxbundle used for Windows Store submission
 * @note This function utalizes the parallels desktop tool "prlctl" to execute windows commands via macOS
 * @param appxPath
 */
function convertAppx2AppxBundle(appxPath) {
    try {
        console.log("Converting Appx to Appxbundle...")
        // We'll use electron-builder's winCodeSign tools which are conveniently already available in the following dir
        var electronBuilderDir = path.join(process.env.HOME, "Library/Caches/electron-builder"), // Don't use "~" it will just not work, trust me...
            // Will use the first matching windowsCodeSigning path as we may have multiple versions installed
            makeAppX = glob.sync(path.join(electronBuilderDir, "winCodeSign", "winCodeSign-*", "windows-10", "x64", "makeappx.exe"))[0],
            appxBundleMapFile = // This file is required by the makeappx.exe to generate the appxbundle
                '[Files]\n' +
                '"\\\\Mac\\AllFiles' + appxPath.replace(/\//g, "\\") + '"\t\t"App.appx"';

        // Save the generated AppxBundle.map file to the filesystem to make it available for the Windows VM
        fs.writeFileSync(path.join(__dirname, "..", "AppxBundle.map"), appxBundleMapFile, { flag: "w" });

        var prlctlArgs = [
            'exec',
            '"Windows 10"', // the name of the specific Windows VM
            '--current-user', // We want to execute the following command with the current user
            // From this point on its the default Windows CLI command for converting an .appx to an .apppxbundle
            // Its important to know that these parts must conform to the Windows style, hence the windowsify function
            // We also need to use double quotation for the network shares due to how childProcess.execSync works...
            '"\\\\\\Mac\\AllFiles' + makeAppX.windowsify() + '"',
            'bundle',
            '/f',
            '"\\\\\\Mac\\AllFiles' + (__dirname.replace("/hooks", "") + "/AppxBundle.map").windowsify() + '"',
            '/p',
            '"\\\\\\Mac\\AllFiles' + appxPath.windowsify() + 'bundle"',
            '/o'
        ];
        // Now just execute the command to convert the appx to an appxbundle
        childProcess.execSync('prlctl ' + prlctlArgs.join(" "), { stdio: 'inherit' });
        console.log("Done converting Appx to Appxbundle");
    } catch (e) {
        console.warn("Couldn't convert appx two appxbundle!");
        console.error(e);
    }
}