Introducing Electron to the Windows Runtime
By Felix Rieseberg and Paul Betts
The Slack Desktop Client is powered by Electron, the same framework that enables Atom, Visual Studio Code, and Basecamp to deliver delightful desktop apps built with web technologies.
This week, we launched Slack for Windows 10 in the Windows Store. It is one of the first applications to make use of Microsoft’s “Desktop Bridge”, previously known as Project Centennial. Slack partnered with Microsoft to pioneer a way for Electron apps to run within the confines of the Windows Store and to integrate with Windows Runtime APIs. Given that we conquered new lands, we wanted to share some of our discoveries.
WinRT: A clubhouse for the most powerful Windows APIs
The Windows Store was previously only available to Universal Windows Apps, which are in many ways the evolution of the good old exe. The store isn’t just a way for users to discover applications — it also offers one-click installations and “no files or registry items left behind” uninstallations. On top of that, it integrates deeply with Microsoft’s IT management tools for enterprises and sysadmins who need to manage software on thousands of machines.
In addition, apps built on top of the Universal Windows Platform get to communicate with Windows through a set of APIs found in the Windows Runtime (usually just called WinRT). It’s the home for the most interesting and most powerful aspects of Windows: If you’d like to interact with hardware, lock screens, payments, notifications, or Cortana, you’re talking to WinRT to make it happen.
Sneaking Electron into the Clubhouse
At the heart of Electron lies Node.js, which can interface with native code through “native addons”. Using dynamically-linked shared objects, written in C or C++, they can be used just as if they were ordinary Node.js modules. The open-source project NodeRT uses WinRT’s descriptive metadata files to iterate over the body of APIs, automatically generating native Node addons for each WinRT namespace. In Electron, this allows us to replace custom C++ with JavaScript.
Example: Setting a Lock Screen Image
using namespace Windows::Storage;
using namespace Windows::System::UserProfile; create_task(myFolder->GetFileAsync(“image.jpg”).then([this](StorageFile^ imageFile) {
if (imageFile != nullptr) {
LockScreen::SetImageFileAsync(imageFile)
}
}
Using NodeRT, we can run the same operation in JavaScript:
const {KnownFolders} = require('windows.storage')
const {LockScreen} = require('windows.system.userprofile')myFolder.getFileAsync('image.jpg', (err, file) => {
LockScreen.setImageFileAsync(file, (err) => { })
})
Many APIs, like the Live Tile API, assume that the calling application is a Universal Windows App — and look for the Store’s package identity to distinguish between applications. In short: To access the full range of WinRT, we also need to wrap Electron in a Windows Store application package.
Under the hood, the Windows Store application format AppX is essentially a zip file that contains an application manifest, static assets, and the binary executable. At runtime, Windows puts Win32 binaries into a virtual environment — write operations to the disk or the registry are virtualized, ensuring that the app leaves no trace after uninstallation.
To compile Electron Apps into the Windows Store application format AppX, we contributed heavily to electron-windows-store, which automates the path from pure Electron app to AppX. In detail, the tool does the following operations:
- Creates an application manifest
- Creates all required static assets
- Packages the binary using either static asset packaging or container installation (the latter being useful for Electron applications with complex installation procedures)
- Creates an AppX bundle with the correct configuration
- Signs the bundle in accordance with Windows guidelines
We also contributed to the development of electron-windows-notifications, which serves as an excellent example for using NodeRT in Electron apps — and can be used in any app to send rich Windows notifications that deeply integrate with the operating system through the Action Center, the Notification Settings, and Quiet Hours.
Looking ahead
We’re very excited about creating an excellent user experience, available on people’s favorite platforms. We’re equally excited about making more APIs and features available to developers working with Electron. If that sounds like an exciting mission to you, come work with us!