NOW LET US – AI RAG SaaS Studio TP.HCM
NOW LET US
Digital Product Studio
Back to news
DEV-TOOLS...6 min read

Windows native app development is a mess

Share
NOW LET US Article – Windows native app development is a mess

A deep dive into the fragmented and frustrating landscape of modern Windows application development, from the evolution of UI frameworks to the hurdles of distribution.

I’m a Windows guy; I always have been. One of my first programming books was Beginning Visual C++ 6, which crucially came with a trial version of Visual C++ that my ten-year-old self could install on my parents’ computer. I remember being on a family vacation when .NET 1.0 came out, working my way through a C# tome and gearing up to rewrite my Neopets cheating programs from MFC into Windows Forms. Even my very first job after university was at a .NET shop, although I worked mostly on the frontend.

While I followed the Windows development ecosystem from the sidelines, my professional work never involved writing native Windows apps. (Chromium is technically a native app, but is more like its own operating system.) And for my hobby projects, the web was always a better choice. But, spurred on by fond childhood memories, I thought writing a fun little Windows utility program might be a good retirement project.

Well. I am here to report that the scene is a complete mess. I totally understand why nobody writes native Windows applications these days, and instead people turn to Electron.

What I built

The utility I built, Display Blackout, scratched an itch for me: when playing games on my three-monitor setup, I wanted to black out my left and right displays. Turning them off will cause Windows to spasm for several seconds and throw all your current window positioning out of whack. But for OLED monitors, throwing up a black overlay will turn off all the pixels, which is just as good.

To be clear, this is not an original idea. I was originally using an AutoHotkey script, which upon writing this post I found out has since morphed into a full Windows application. Other incarnations of the idea are even available on the Microsoft Store. But, I thought I could create a slightly nicer and more modern UI, and anyway, the point was to learn, not to create a commercial product.

For our purposes, what’s interesting about this app is the sort of capabilities it needs:

  • Enumerating the machine’s displays and their bounds
  • Placing borderless, titlebar-less, non-activating black windows
  • Intercepting a global keyboard shortcut
  • Optionally running at startup
  • Storing some persistent settings
  • Displaying a tray icon with a few menu items

Let’s keep those in mind going forward.

A brief history of Windows programming

In the beginning, there was the Win32 API, in C. Unfortunately, this API is still highly relevant today, including for my program.

Over time, a series of abstractions on top of this emerged. The main pre-.NET one was the MFC C++ library, which used modern-at-the-time language features like classes and templates to add some object-orientation on top of the raw C functions.

The abstraction train really got going with the introduction of .NET. .NET was many things, but for our purposes the most important part was the introduction of a new programming language, C#, that ran as JITed bytecode on a new virtual machine, in the same style as Java. This brought automatic memory management (and thus memory safety) to Windows programming, and generally gave Microsoft a more modern foundation for their ecosystem. Additionally, the .NET libraries included a whole new set of APIs for interacting with Windows. On the UI side in particular, .NET 1.0 (2002) started out with Windows Forms. Similar to MFC, it was largely a wrapper around the Win32 windowing and control APIs.

With .NET 3.0 (2006), Microsoft introduced WPF. Now, instead of creating all controls as C# objects, there was a separate markup language, XAML: more like the HTML + JavaScript relationship. This also was the first time they redrew controls from scratch, on the GPU, instead of wrapping the Win32 API controls that shipped with the OS. At the time, this felt like a fresh start, and a good foundation for the foreseeable future of Windows apps.

The next big pivot was with the release of Windows 8 (2012) and the introduction of WinRT. Similar to .NET, it was an attempt to create new APIs for all of the functionality needed to write Windows applications. If developers stayed inside the lines of WinRT, their apps would meet the modern standard of sandboxed apps, such as those on Android and iOS, and be deployable across Windows desktops, tablets, and phones. It was still XAML-based on the UI side, but with everything slightly different than it was in WPF, to support the more constrained cross-device targets.

This strategy got a do-over in Windows 10 (2015) with UWP, with some sandboxing restrictions lifted to allow for more capable desktop/phone/Xbox/HoloLens apps, but still not quite the same power as full .NET apps with WPF. At the same time, with both WinRT and UWP, certain new OS-level features and integrations (such as push notifications, live tiles, or publication in the Microsoft Store) were only granted to apps that used these frameworks. This led to awkward architectures where applications like Chrome or Microsoft Office would have WinRT/UWP bridge apps around old-school cores, communicating over IPC or similar.

With Windows 11 (2021), Microsoft finally gave up on the attempts to move everyone to some more-sandboxed and more-modern platform. The Windows App SDK exposes all the formerly WinRT/UWP-exclusive features to all Windows apps, whether written in standard C++ (no more C++/CLI) or written in .NET. The SDK includes WinUI 3, yet another XAML-based, drawn-from-scratch control library.

So did you catch all that? Just looking at the UI framework evolution, we have:

Win32 C APIs → MFC → WinForms → WPF → WinRT XAML → UWP XAML → WinUI 3

Forks in the road

In the spirit of this being a learning project, I knew I wanted to use the latest and greatest first-party foundation. That meant writing a WinUI 3 app, using the Windows App SDK. There ends up being three ways to go about this:

This is a painful choice. C++ will produce lean apps, runtime-linked against the Windows APP SDK libraries, with easy interop down into any Win32 C APIs that I might need. But, in 2026, writing a greenfield application in a memory-unsafe language like C++ is a crime.

What would be ideal is if I could use the system’s .NET, and just distribute the C# bytecode, similar to how all web apps share the same web platform provided by the browser. This is called “framework-dependent deployment”. However, for no reason I can understand, Microsoft has decided that even the latest versions of Windows 11 only get .NET 4.8.1 preinstalled. (The current version of .NET is 10.) So distributing an app this way incurs a tragedy of the commons, where the first app to need modern .NET will cause Windows to show a dialog prompting the user to download and install the .NET libraries. This is not the optimal user experience!

That leaves .NET AOT. Yes, I am compiling the entire .NET runtime—including the virtual machine, garbage collector, standard library, etc.—into my binary. The compiler tries to trim out unused code, but the result is still a solid 9 MiB for an app that blacks out some monitors.

(“What about Rust?” I hear you ask. A Microsoft-adjacent effort to maintain Rust bindings for the Windows App SDK was tried, but they gave up.)

There’s a similar painful choice when it comes to distribution. Although Windows is happy to support hand-rolled or third-party-tool-generated setup.exe installers, the Microsoft-recommended path for a modern app with containerized install/uninstall is MSIX. But this format relies heavily on code signing certificates, which seem to cost around $200–300/year for non-US residents. The unsigned sideloading experience is terrible, requiring a cryptic PowerShell command only usable from an admin terminal. I could avoid sideloading if Microsoft would just accept my app into their store, but they rejected it for not offering “unique lasting value”.

The tragedy here is that this all seems so unnecessary. .NET could be distributed via Windows Update, so the latest version is always pr

© 2026 Now Let Us. All rights reserved.

Source: Hacker News

Advertisement
Ad slot ready: 5887729102

More in this category

EXPLORE TOPICS

Discover All Categories

Deep dive into the specific technology sectors that matter most to you.