Developing Desktop Apps for Windows: XAML Islands vs WinUI vs UWP
By: Nicolás Bello Camilletti
Tags: Winui, Uwp, Csharp, Xaml, Windows

Our Case

We wanted the modern-looking UI, but several doubts arose about accessing OS resources, as we would most likely need extensive access to the file system and the global registry. Then, instead of going directly with UWP, we decided to try an alternative that would give us unrestricted access to those resource and a modern-looking UI.

XAML Islands

XAML Islands is basically a way to add UWP UI controls into desktop applications. Our intent was to do everything we could in UWP, but have the base application be a desktop application so that we would not have troubles when trying to access restricted resources. Everything went well at first, but soon we started finding several limitations. Here is a list of “limitations and workarounds” in the official XAML Islands documentation. Although most of times it is hard to explore deeper into all limitations just by looking such kind of lists.

For example, we thought it would be good to use UWP file pickers in some parts of the UI, but it turns out that XAML Islands do not support open dialogs so pickers will fail. There is a workaround explained here using the IInitializeWithWindow pattern, but this starts showing how many things become harder to implement.

As another example, we wanted to be able to open our application from the system tray and hide it when closed. This is easy to do in WPF, you just hide the Window and the corresponding taskbar icon when initializing the app. But when initializing an application using XAML Islands, a taskbar icon from a process that was not even part of our application appears, and it would not go away until we showed a window. We did a non-elegant work-around of creating an additional transparent window and then removing it just to make that icon go away. We also had to find workarounds for other features like theme changes.

Figuring out how to…

The main problem with XAML Islands is not only that it has so many limitations, but more importantly, that there is very little documentation other than the official one. This caused us to have to spend hours or days for every one of these workarounds we had to do.

Furthermore, we had seen in this official documentation that some Windows APIs can be called from a desktop application. This would be helpful as some APIs from the Windows Runtime API were more appropriate for our use than the .NET ones, but when we tried to use them, most of the Windows APIs require a package identity, and this package identity would place the restrictions like making it a full UWP app, partially defeating the purpose of not using UWP.

This may change in the future, as it seems that starting from Windows 10 May 2020 Update (version 2004), desktop applications are allowed to have a package identity without having to be placed in a sandbox (More information).

If you decide to go with XAML Islands, other than the official documentation, this post from the Windows Developer blog can prove very useful.

At this point, we thought it may be better to try just going full UWP instead.

Full UWP desktop apps using the FullTrustProcessLauncher API

One of the first things we noticed when starting our prototype in UWP is that the systray icon does not exist in UWP. For this, and other requirements that would potentially need a desktop application, we looked for an alternative, and found the FullTrustProcessLauncher API. This API basically allows a desktop application to be launched from another UWP application, and vice-versa.

To be able to use the FullTrustProcessLauncher API, the runFullTrust restricted capability must be added to the manifest.

In our case, our desktop application only contained the taskbar component with a menu to open the UWP one.

Desktop applications can be uploaded to the Microsoft Store, but keep in mind that doing so will require a more complicated (and onerous) process than with UWP apps because it contains the runFullTrust restricted capability. (More information)

One of the biggest differences between UWP and desktop apps, the Application Lifecycle

Since UWP aims to create applications for both desktop and mobile devices, its lifecycle process must take into consideration the battery restrictions on mobile devices. As such, UWP applications normally cannot run indefinitely hidden in the background as desktop apps can. We say normally because Microsoft added in its Windows version 1703, a set of APIs to allow extended or indefinite execution in the background, but that has other restrictions.

In UWP, if you close an application, it directly goes to the “Not Running” state, which means the process is killed, and you lose any non-saved data. If you do not close it, but instead minimize it, or change focus to another application, then after a few seconds the application will be suspended. When an application is suspended, there is the possibility that the system may terminate its process if it needs the resources, or if it is drawing too much battery. Therefore, it is needed to save the application state before the application goes into the suspended state. UWP apps can have a handler function set to its Suspended event, where they can save the state. This execution is limited to 5 seconds (10 for mobile devices), so Microsoft recommends partially saving application data while it is still running so that smaller operations are needed on the suspended event. If the handler of the Suspended event does not finish within the time limit, the application will be terminated.

The Application Lifecycle

Executing code from the background in UWP

The UWP way to do background processing is using Background Tasks. These tasks are classes that are registered to execute code when certain conditions are met, even if the application is not currently running at that time. Once a task is registered, it will last until unregistered, until the application is uninstalled or reinstalled, but it is recommended to re-register them on application launch.

There are several different triggers that allow for many conditions for starting execution, but there is another limitation, which is resources. Background tasks can run up to 10 minutes if the app is running in the foreground, or 30 seconds otherwise. This can be a limitation for many desktop applications that need to do intensive background processing. The execution time can be extended indefinitely by setting the extendedExecutionUnconstrained capability in the manifest.

Be aware that adding the extendedExecutionUnconstrained restricted capability will prevent the application from being deployable to the Microsoft Store.

Another issue to watch out for is that background tasks may be limited by the system in their memory usage, as they are expected to be lightweight. In the official documentation, there are guidelines for creating background tasks, but overall, they seem to be aimed at doing minor tasks.

Windows Control

Another difference between UWP and WPF or XAML Islands is the way windows are controlled. Controlling windows in UWP is more restricted.

Package limitations

One last issue we will mention in this post is the limitations that are inherent in requiring an MSIX package. Another feature we wanted to have was to add a shell extension to, for example, provide additional functionality to the file explorer context menu, and add overlay icons. In a desktop application, we could do this by using Shell extension handlers. The problem is that to register these extensions, we needed to modify the global registry, and this is not allowed in packaged applications.

After some investigations, it seems that it is possible to do things like adding shell extensions, but the way to do it is using the package manifest schema. The problem with using the package manifest schema is that the official documentation is quite scarce, and documentation other than the official one is almost non-existent. So, it is a thing to have in consideration, that features which need the global registry to be modified (for example, if another application needs to access these modifications) are possible but doing it can take a long time.