Using web technologies to create desktop apps has been around for quite some time now, with frameworks like Electron being mature and used in lots of products, such as Spotify and Slack. I've only ever used it for side projects, until finally this week a customer asked me if I could provide a desktop application of our popular WebGAEB converter. Of course I could! So I sat down at my computer and made an ASP.NET Core MVC app into a desktop app, bundled as a single executable file.
This approach works by bundling everything together - your frontend, sometimes even your ASP.NET Core backend server and it's own embedded browser. This has been a bit polarizing in the last years among various communities. It's great for developer productivity, but it's also a very wasteful way to use a computers resources.
However, I'm leaning heavily towards productivity to be able to quickly build features our users care about. I could have built a dedicated .NET WPF app from scratch, or I could just use Electron and be done in two hours. That's what I'd like to share with you in this blog post.
The following is the complete build target for Nuke Build. You're free to use something else to orchestrate your build, but even if you're unfamiliar with this tool, you'll see that it's quite straightforward:
I'll explain the script step-by-step, but I will skip the trivial parts, like copying the files to the output directory. If anything is unclear, please leave a comment!
Electron.NET is an integration for the the Electron package with ASP.NET Core. It's got a great documentation at it's project site, so I'm not going to deeply into the details.
When you set up your ASP.NET Core project, you're using the Electron.NET package to instrument the interaction with the Electron shell. The result will be a self contained deployment that bundles the Kestrel server into your app.
The Dangl.WebGAEB solution uses a Standalone configuration which sets up some things differently in contrast to the web deployment. For example, I'm using embedded services instead of calling a REST API. This heavily depends on your app as a whole and is not covered in this post.
Build a Single Executable File with Warp
While Electron itself is cool and all, it's Node.js heritage really shows: After the app is created, you'll have a folder with tons of files. This isn't a problem if you're doing some big business app with an installer, but I simply want a single executable file, .exe for Windows in my case. I remembered the Warp project, which I've read about some time ago. This tool takes a folder, bundles it into a single executable file and lets you specify an entry point.
Change the Generated Exe to Hide its Console Window
One drawback to this approach is that warp internally starts your ASP.NET Core application, which itself is a console host. The final Electron window is then again launched from your ASP.NET Core server. This means there will be an additional console window present, besides your app. This won't fly with users, so it has to be disabled.
Truth is, I'm not really familiar with how this works. But there's some metadata in executable files on Windows. One of them is whether or not an .exe should show it's console host. Unfortunately, this isn't configurable until .NET Core 3.0, so we have to find another way. Fortunately, there's a great wiki page on the AvaloniaUI GitHub page. It's explain how the editbin.exe utility, which is included in Visual Studio, can be used to patch your executable. So just go find editbin.exe in your Visual Studio installation folder and you're good to go!
Upload your Artifacts
Your final result will be a single executable file. Which contains your ASP.NET Core backend, the Kestrel webserver, your frontend, and last but not least, a full web browser. I see where the critics saying this is wasteful are coming from, but it just works amazingly well😊
This example is pushing the artifacts, along with some documentation, to DanglDocu. There, my customers get notified about new releases and can download it. For you, that's probably different!
You can check out the online version of WebGAEB. It's basically the same as the GAEB converter on this site, except it's in German. The cleverly named "Desktop Edition" looks like this and runs 100% locally: