Running real Windows 8 apps... in Electron?

Any discussion of software that doesn't fit into any category goes here.
Post Reply
User avatar
Wam
Posts: 26
Joined: Thu Dec 08, 2022 12:55 pm

Running real Windows 8 apps... in Electron?

Post by Wam »

Windows 8 was a... controversial release for many. As we well know, end users didn't really like the touch oriented interface, but for developers there was a much more interesting conundrum. How were those touch oriented apps going to get made?

In previous years, Microsoft had been touting Silverlight, the ill-fated browser plugin at their developer events like MIX, showing it as the foundation for apps on the similarly ill-fated Windows Phone 7. Silverlight was based on .NET, so .NET developers (the C# and VB.NET folk of the world) were living their best lives.

Then came BUILD 2012. The unveiling of Windows 8, and by extension its whole new app platform... and the focus wasn't .NET, or Silverlight, but HTML5 and JavaScript. Microsoft expected that as part of the next generation of Windows apps, web technologies were going to be a first class way to write apps for the platform, and they MEANT it. Of all the pre-loaded metro apps included in Windows 8's developer preview, 22/30 were written this way, and fast forward 2 years to the final versions of Windows 8.1, every app marked here is too.

JS8.png

Developer reactions were mixed. Existing .NET developers felt they were being put on the back burner(even though they really weren't, as we'll explore later), and JS developers were mixed too as Microsoft has had... let's say a rocky relationship with the web.

Obviously, now Windows 8.1 is no longer supported, slowly falling out of service and its online servers are slowly being taken offline, we aren't going to be able to run these apps forever, especially not in their original state and form... which lead me to wonder. If these apps are effectively just webapps... could they not run in a web *browser*?
User avatar
Wam
Posts: 26
Joined: Thu Dec 08, 2022 12:55 pm

Re: Running real Windows 8 apps... in Electron?

Post by Wam »

The Windows Runtime
Apps and websites are not the same thing, no matter how much Google and Mozilla want you to think they are. The trust model, i.e. the things they're allowed to do on the end user's machine, is very different between the two. Users don't want a website being able to access all their files, photos, contacts, emails, etc. but they do expect apps to be able to interact with them. Microsoft knew this, so they needed a way to allow these new JS apps to access system level APIs, but also wanted to support .NET and C++ developers at the same time.

So along comes the Windows Runtime. At its core it's actually nothing super new, it's a subset of the legacy COM interface, but instead of obscure headers and typelibs, types (aka classes, interfaces, structures, enumerations, events and delegates) are all defined in "Metadata" files with the extension ".winmd". Some of this metadata was provided by the system for OS level APIs, usually with the prefix "Windows.", but apps could write their own code in C++ or C# and expose it to a JavaScript (or C#, or C++) frontend through the same system. Microsoft added native support for these types to .NET, as well as Chakra (the JS engine powering IE) and their MSVC compiler. The winmd format itself is also relatively simple, being a subset of the ECMA-335 standard used for .NET assemblies, you can even list these APIs in .NET Decompilers like ILSpy and DotPeek.

dotPeek64_ducCF3x32C.png

If my goal was to run these apps in a browser, I would have to somehow "shim" this functionality, and expose it to JavaScript... from JavaScript.

When in JS, each namespace was exposed through an object in the global scope, and could be accessed like so:

Code: Select all

var localFolder = Windows.Storage.ApplicationData.current.localFolder;
localFolder.createFileAsync("test.txt")
           .then(function(file) { 
                return Windows.Storage.FileIO.writeTextAsync(file, "Hello, world!");
           });
Initially I started writing out these large object hierarchies by hand, but I quickly realised I was going to need something a little bit more automated. So I dug around and found C++/WinRT, which used a small generator program to take Windows Runtime metadata and output C++ headers capable of consuming them. I took the reader portion, and forked this into what I coined TS/WinRT, which when fed Windows Runtime Metadata, would create a huge folder tree of TypeScript modules for each corresponding type, as well as a glue file that would organise each module into its corresponding namespace, and expose this to the global scope

Code_89Vlg77M6o.png

From here, I can implement each required class, function, and so on. This is a painstaking process. Windows itself has thousands of APIs and every single app adds even more and on top of this, quickly realised that a web browser would not give me the freedom I needed...
User avatar
Wam
Posts: 26
Joined: Thu Dec 08, 2022 12:55 pm

Re: Running real Windows 8 apps... in Electron?

Post by Wam »

ms-appx://
Windows 8 apps didn't use any regular protocol like http:// or https:// or even file://. They used a custom protocol named ms-appx:. This protocol has a number of weird quirks but the big one is resources.pri.

The protocol is actually relatively well documented, but the documentation notes something crucial
If the path refers to a physical path and file name then that physical file asset is retrieved. But if no such physical file is found then the actual resource returned during retrieval is determined by using content negotiation at runtime. This determination is based on app, OS, and user settings such as language, display scale factor, theme, high contrast, and other runtime contexts. For example, a combination of the app's languages, the system's display settings, and the user's high contrast settings may be taken into account when determining the actual resource value to be retrieved.

Code: Select all

ms-appx:///images/logo.png
The URI above may actually retrieve a file within the current app's package with the following physical file name.

Code: Select all

\Images\fr-FR\logo.scale-100_contrast-white.png
In short, this means there is not actually a 1:1 mapping of "files in ms-appx: URLs", and "files on disk". There has to be a lookup table, and this is where the resources.pri file comes in.

7zFM_W9IUcsqs5P.png

I've avoided talking about the structure of .appx packages themselves up until this point because it's not super critical, but in the root directory of the package sits a file named "resources.pri" which contains app resource strings in a proprietary binary format. Not wanting to parse that in JavaScript here comes tool number two! to convert these files into JSON, which is then loaded by Node.js and used in Electron as a custom URL scheme so apps load their correct resources.
Last edited by Wam on Wed Jan 18, 2023 4:41 pm, edited 1 time in total.
User avatar
Wam
Posts: 26
Joined: Thu Dec 08, 2022 12:55 pm

Re: Running real Windows 8 apps... in Electron?

Post by Wam »

The Shell
Note: The shell is currently undergoing a large-ish rewrite for accuracy, so this information may be out of date in future

electron_cwn8IKzink.png

It wouldn't be Windows 8 without tiles, and while my custom HTML shell may look kinda pretty, it also actually serves a number of important functions including:
  • App activation & lifecycle
  • Splash screens
  • The Windows.UI.Popups.MessageDialog API
  • The Windows.UI.Popups.PopupMenu API
  • The Windows.UI.ApplicationSettings.SettingsPane API
  • Live Tile APIs (soon)
  • Toast Notification APIs (soon)
User avatar
Wam
Posts: 26
Joined: Thu Dec 08, 2022 12:55 pm

Re: Running real Windows 8 apps... in Electron?

Post by Wam »

The Browser
The last hurdle is of course, Internet Explorer itself. And this is, unfortunately, where I've had to modify many app files in order to get anywhere. Everything from depending on ActiveX controls, to IE-specific extensions to the web like MSPointerEvent and CSS features like -ms-flex and -ms-grid. There's no complete way to pollyfil these, so there's scripts written to translate CSS ahead of time.

But finally...
User avatar
Wam
Posts: 26
Joined: Thu Dec 08, 2022 12:55 pm

Re: Running real Windows 8 apps... in Electron?

Post by Wam »

The Apps

Perfect: Cut the Rope

Games tend to be built in a less browser specific way, so Cut the Rope works perfectly.

electron_7QSlFv8g9U.png


Perfect: Game Dev Tycoon

Similar to the above, I've actually played a lot of this game in this sandbox

electron_USk8wFF2AA.png

Working: People

Launches, animates correctly, will show contacts and allow you to create them.

electron_ltGDbJLvtZ.png

Working: Xbox Music

The music app opens, scans for music on the local machine, presents an album/artist/song view and even has a WIP web streaming backend!

electron_KEvg2des0S.png

Functional: Skype

Connects to a Discord backend because I thought that'd be funny. Loads, logs in, plays the all important sound. Can't yet send messages.

electron_tHdEqt0c1v.png

Functional: Xbox Video

Not as feature complete as its auditory counterpart but will play videos if one is dragged onto its tile.

electron_1OOt1udeq1.png

Functional: Mail

Launches, the editor works, that's kinda about it though.

electron_yvvlEKmwqG.png

Functional: Calendar

Launches, month view works.

electron_7Me1jHztKn.png
User avatar
MattKC
Site Admin
Posts: 323
Joined: Mon Aug 22, 2022 1:05 am
Contact:

Re: Running real Windows 8 apps... in Electron?

Post by MattKC »

This is amazing work, great write up!

So does Electron provide enough permissions to theoretically reimplement everything? When you mentioned file system read/write, I got worried because I know browsers don't provide that kind of access (for good reason), but I guess Electron must because so many code editors are written in it haha
User avatar
Wam
Posts: 26
Joined: Thu Dec 08, 2022 12:55 pm

Re: Running real Windows 8 apps... in Electron?

Post by Wam »

It's configurable whether any given Electron "WebContents" (like a frame or window) can access node.js APIs. If they can, they have effectively complete control over the machine (including the ability to load JS over https), however typically that's not the default and they have quite a lot of documentation on how to secure your apps against this stuff

https://www.electronjs.org/docs/latest/ ... l/security

Does everyone read it? Good question. Am I following security best practices here? Not remotely, but also all code is loaded from files on disk nothing over the internet.
Post Reply