Packaging an Electron app for managed distribution across devices

  • April 17, 2018
  • Views

     18,413

Introduction

A customer we were recently collaborating with came to us with an interesting problem regarding their cross platform codebase and managed distribution. We learned that they were planning to build an Electron-based application and needed help from Microsoft to understand how to build, deploy and manage the application on Windows using an MDM solution (eg. Microsoft Intune). Microsoft Intune is a cloud service that provides mobile device management and mobile application management capabilities. Together with the customer, Microsoft engineers built a sample electron application that could be opened in Kiosk mode and could be deployed through Microsoft Intune.

In this code story, we’ll explore the following aspects of our solution:

  • Packaging Electron source into Windows binaries
  • Setting the app in ‘Kiosk’ mode using PowerShell
  • Building a Configurable Windows installer (.MSI) using WiX Toolset
  • Cross-platform CI with AppVeyor and Travis

In order to focus on these aspects, we created a sample Electron app and iterated on it.

Windows Binaries

In perhaps the most straightforward part of our journey, we used the Electron Packager CLI tool to create OS-specific bundles from an Electron app.

Kiosk Mode

Windows 10 Enterprise provides multiple ways to run an app in kiosk mode:

  • Assigned Access method, which allows a single Universal Windows Platform (UWP) app to run in kiosk mode.
  • Shell Launcher method, which allows a single classic Windows Application (e.g Electron app) to run in kiosk mode.

Intune provides a built-in Configuration Service Provider to remote-enable Assigned Access. It is as simple as providing a JSON with domain/local username and the UWP Application ID in  Azure Portal.

Since Electron is a classic Windows app, we chose Shell Launcher as our way forward.

Shell Launcher

Because Intune does not provide a direct way to remote-enable Shell Launcher, we had to use an elevated PowerShell script. The script takes the local/domain username as well as the full path of the Windows executable (.exe) produced in the previous step as parameters.

We turned on the Shell Launcher feature in Windows 10 (Programs and Features -> Turn Windows features on or off -> Expand ‘Device Lockdown’ -> Select Shell Launcher). Below is the code to do the same in PowerShell:

Then we created a Shell Launcher Object as provided by Windows Management Instrumentation (WMI).

In order to set a custom shell, we had to first find out the Security Identifier (SID) of the Windows username. We wrote a helper function for this:

Finally, we set the custom shell for the above SID and full application path:

For debugging purposes we also print modified shell settings:

If ShellLauncher was successfully updated, the output of this command would be:

Windows Auto-Logon

To provide a full kiosk experience, we decided to auto-login the kiosk user. For this step, we added another parameter $Password to the PowerShell Script and modify Windows Registry.

Windows Installer

For building Windows Installers for Electron apps, the most popular choice is the Squirrel-based electron-winstaller npm module. However, electron-winstaller does not allow custom parameters for the produced installer or executing elevated PowerShell; as a result, we chose to use  WiX Toolset (specifically, we chose the npm module wixtoolset-compiler). When executed normally, the installer prompts for Windows elevation; however, apps distributed with Intune are installed without interruption via the SYSTEM user, which keeps the elevation prompt silent.

WiX Toolset

Building a Windows installer with WiX is a multi-step process. The first step is to configure it with an XML file (.wxs). We have provided a base config file product.wxs that contains app name, version, author, a unique upgrade code, installer parameters with default values, as well as custom actions that execute our PowerShell script.

Then we execute WiX steps in this order:

1) Heat

Heat is a binary harvester that scans through folders or .NET solutions (.sln) for Windows binaries and generates an XML output with a list of files.

Here is a part of the generated heat.wxs output:

2) Candle

Candle pre-processes .wxs files and generates compiled .wixobj files. We passed the above .wxs files to Candle.

3) Light

The Light tool processes the previously mentioned .wixobj files and produces the final installer (.MSI).

The previous WiX steps were wrapped inside npm scripts. Here is how the package.json looks:

Next, generate the installer in the /dist folder:

The installer can simply be invoked by:

Distributing the generated .msi with Intune in the Azure Portal

Continuous Integration

AppVeyor

We wanted to make sure we had a way to verify that changes in Electron app or PowerShell script continue to produce an installer that correctly sets the app in kiosk mode, so we used AppVeyor CI to build and execute the installer on AppVeyor’s Windows build agent as well as produce an installation log file.

Here is the appveyor.yml:

Travis CI

Building Windows installers on a Linux environment is uncommon, and we ran into a few challenges.

In order to isolate Wine and Winetricks setup, we used an existing Linux Docker image which contained WiX Toolset, Wine and Node.js, to create our app’s Docker image.

We then added these Docker commands to npm scripts which build the image, create the container and copy the artifacts from the container to host machine.

Here is the final Travis CI configuration:

Conclusion

Through our collaboration with the customer, we were able to build a simple Electron-based app that we could deploy to a broad range of devices using Microsoft Intune.  While we used a simple Electron app here, you can easily use the scripts and code that we developed here for other projects where you want to manage and customize the deployment of Electron apps.

Resources

You can reach out to us with feedback and questions in the comments below.

Related Articles

Leave a reply

Your email address will not be published. Required fields are marked *

2018-11-30 01:26:18

Syed Hassaan Ahmed says:

Hi,We discovered that the Windows Embedded Shell Launcher feature requires Windows 10 Enterprise version, hence we've updated the GitHub repo. Are you getting a black screen on the Enterprise version?Kiosk mode shouldn't be enabled for all users as the PowerShell script only works for a specific user. Have you checked the installer logs and PowerShell logs as specified in the GitHub readme?

2018-11-27 05:25:54

Nicolas says:

Tried your demo on a old laptop. Installation went fine, autologin was set up, but I also get a black screen.Worst thing is that Kiosk mode seems to be enabled for all user, so I had to reinstall windows completely as I couldn't get back to my dev session.I passed the correct username and password during install though... Do you have any clue on what's happening ?

2018-11-16 02:20:50

Jim Holland says:

Hi, nice work, but we cannot get it to work. We just get a black screen on the kiosk. Username and password is confirmed correct. MSI log is normal - no errors or warnings. Kiosk Demo is correctly installed. It all looks right but only a black screen on login (explorer.exe is not started). We're running Windows 10 Pro (1803). Any ideas what might be wrong?

2018-10-14 15:39:30

Prince D says:

Thank you for the reply sir! i did not realize you made a reply until today. I will try what you have mentioned. Do you have colleagues or team members that have your skillset, and may be available for paid consultation on this topic? I tried to reach your through my Field Engineers and TAMs but maybe you are on a different project lately.

2018-09-15 13:43:30

Syed Hassaan Ahmed says:

Hi,When you build the solution with npm run dist the created installer already contains binaries from a sample Electron app. If you'd like to insert your own Electron app, you should modify the code in /src directory. Due to the sample app mentioned above, you should not see a completely black screen. When executing the installer, did you specify the correct KIOSK_USERNAME and KIOSK_PASSWORD parameters? Also you should enable installer logging like below and check for errors msiexec /i "setup.msi" /l*v "msi.log" KIOSK_USERNAME=... KIOSK_PASSWORD=.... The PowerShell script which is executed by installer, creates a log at C:\Windows\SysWOW64\powershell.log. You should check the content of that log too.

2018-09-13 17:39:15

Prince D says:

This is awesome, and EXACTLY what i need for a very big project that i am on. I realize it is far too difficult to consistently supress the windows shell into a secure state, so replacing it is the only option. I compiled and installed this solution and it landed me on the Kiosk User account completely black, as expected. where do i insert an actual Electron app that will load after the MSI installs? i am making KIOSK desktops that require just a few icons to open applications installed locally,and a browser locked down to a few sites.