Update March 2024
Publishing a WinUI 3 app as a single exe is now possible. Check out my new post about this topic https://johnnys.news/2024/03/Revisited-WinUI-publishing-a-single-exe.
TL;DR
if you have an idea on how to publish a .NET MAUI app as a single file for Windows, please let me know. I tried everything i could find on the internet in the docs and on GitHub but nothing worked.
.NET MAUI publishing
this is my biggest pain point with .NET MAUI at the moment. I have a very simple requirement for one of my applications. My goal was to publish and distribute a single file for both macOS and Windows. On macOS this is easy a build of the application generates a .app file. Actually, this is not really a single file as you can show and navigate the package contents but for distribution this works very well (once code signing is done) - just click and run, beautiful ☀️
Usually, developers tend to complain about apple platforms when it comes to publishing and distribution but the hours and effort i invested in getting a Windows app published are just insane. On the apple side it’s mostly code signing and notarization which can be tricky - if you are interested about this feel free to check the code of my action for Dots on GitHub. But in this post i want to focus on Windows publishing and some of my findings from the last couple of days were i tried to get a .NET MAUI application published.
Right click -> Publish
The obvious first thing for a developer who spends most of his time inside Visual Studio is the classic right click -> Publish. I quickly found out this this simply crashes the IDE immediately 💥 great start…
Since i have used single file executables in the past in dotnet apps the next thing i tried was setting the <PublishSingleFile>
flag to true
. The <PublishSingleFile>true</PublishSingleFile>
flag works fine for dotnet projects like console apps but just fails for .NET MAUI (more specifically Windows App SDK) projects. Calling dotnet publish -f net7.0-windows10.0.19041.0 -c Release
shows the following error
1 | C:\Program Files\dotnet\sdk\7.0.200-preview.22628.1\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.CrossGen.targets(465,5): |
Next step was to set PublishReadyToRun
to false - as indicated by the error message. A pity since i want to use ReadyToRun for a better app performance. I still tried it to see if i can get a single executable.
This time the build succeeded, and a bigger executable was created in the publish folder. I thought i was done - but no…
The application simply fails to launch. The Windows event viewer shows the following error.
Turns out that i’m not the only one with this issue - there are dozens of reports and similar issues on StackOverflow and GitHub spread across multiple repositories:
https://github.com/microsoft/WindowsAppSDK/issues/3042
https://github.com/microsoft/microsoft-ui-xaml/issues/7143
https://github.com/dotnet/maui/issues/4329
WinUI3 + Windows App SDK
To investigate further i stopped experimenting with a .NET MAUI project and created a blank WinUI 3 + Windows App SDK project, since this is what MAUI for Windows is based on. I followed the steps from the documentation and set up the project to be unpackaged. I tried to use a configuration which bundles the runtime and the Windows App SDK with the application to have a single exe to distribute.
1 | <PublishSingleFile>true</PublishSingleFile> |
Since i don’t want to publish a MSIX installer - i removed the Package.appxmanifest
from the project and changed my launchSettings.json to only include the unpackaged configuration:
1 | { |
I used the following command to publish the application:
1 | dotnet publish -f net7.0-windows10.0.19041.0 -c Release -p:Platform=x64 |
and got the output that a task is missing:
1 | C:\Users\dev\.nuget\packages\microsoft.windowsappsdk\1.2.221209.1\buildTransitive\MrtCore |
If someone has a solution to this i would be very happy to hear about it - so far i was not able to get even a blank WinUI 3 application published as a single file. I experimented with AOT and ReadyToRun builds (with and without trimming) which all work fine, but as soon I set true
the application fails to launch. I ended up with a very frustrating trial-and-error approach to test all possible combinations of the following flags in the csproj file:
1 | <PublishSingleFile> |
but had no luck - neither from the command line via dotnet publish
nor from Visual Studio -> Publish. Some of these flags are not even documented i just found them randomly on GitHub, StackOverflow or in the targets source code.
Unpackaged Application
at this point i gave up on my single file goal and tried to publish the application with all default settings and the standard dotnet publish
command. All i did was changing WindowsPackageType
from MSIX
to <WindowsPackageType>None</WindowsPackageType>
. This setup should produce an unpackaged application (terrible naming btw). I’m now calling dotnet publish -f net7.0-windows10.0.19041.0 -c Release
which produces a publish folder in bin/Release/net7.0-windows10.0.19041.0 which contains an executable and a whole bunch of required dlls and localization directories.
With over 416 files i clearly missed my goal of publishing a single executable. But at the current level of frustration i thought so far so good - i can just zip this folder and distribute it. But no - the application launches but assets like images and fonts are not loaded. At this point a build of Dots would look like this:
Back to GitHub and StackOverflow to find a solution. Turns out that there are some open issues in MAUI and Windows App SDK, but they don’t have any traction or recent updates:
https://github.com/dotnet/maui/issues/10526
https://github.com/microsoft/Win2D/issues/891
https://github.com/microsoft/microsoft-ui-xaml/issues/7866
https://github.com/dotnet/maui/issues/10899
https://github.com/dotnet/maui/issues/9104
I’m also using a custom font to my blank WinUI 3 project, and it also fails to render the glyphs. So, this one is most probably a general issue with the Windows App SDK and not specific to .NET MAUI. The underlying issue seems to be:
https://github.com/microsoft/Win2D/issues/891
which is now tracked as an internal non-public workitem.
I could find possible a workaround for the missing images, but on my side this again creates an exe that crashes on launch with the same error shown in the event viewer as above.
<RANT>
At this point i’m in a love hate relationship with .NET MAUI. I really like the idea of a single .NET framework for all platforms and the abstractions that MAUI provides to simplify some boilerplate tasks for cross platform development. On the other hand, i think that the current state of MAUI is still not great for developers. Critical issues are not fixed for months, and basic functionality is broken. Critical bugfixes get backported, but still developers have to wait for a Visual Studio update to get the fix (or rollback workloads manually which is a terrible experience). From my outside perspective it seems that the MAUI engineering team is understaffed, and engineers are too busy with fixing bugs and don’t even have the possibility to work on real innovations in the cross-platform space. If you compare it with the progress that Flutter or similar projects in the .NET ecosystem have made recently it feels like a joke. I feel really sorry for the developers that are working on MAUI, i see it daily in the GitHub repository that they are continuously working hard. But for me as a developer who is following the project across social media and podcasts it’s just frustrating to hear from PMs that everything MAUI is just “latest and greatest and perfectly shiny” - i don’t have such feelings when i try to publish my app, right now. As said i’m an active follower of the dotnet/maui repository i am of course aware of the issues that track the problems that i’m facing right now, but similar to a majority of the open issues those are not getting any attention and are just added to the backlog.
https://github.com/dotnet/maui/issues/3166
https://github.com/dotnet/maui/issues/10564
I mean it’s just infuriating when a framework is declared “production-ready”, but it can’t even produce a working app on Windows - where the SDK is maintained by a group in the same division of the company. It feels like the Windows App SDK is far from being a stable solid foundation for MAUI on Windows.
Maybe i am just too stupid to get this working or if publishing an app as a single executable is just a requirement that’s too exotic in 2023. I have been working with .NET since 2008 and i have never had such a frustrating experience with publishing an application. Documentation (which is usually very good for .NET) is either non-existent, outdated or simply too hard to find - i have the feeling that very specific knowledge is spread across the internet buried in GitHub issues or StackOverflow threads. I ended up with a lot of trial-and-error attempts and this blog post where i try to describe some of my findings from this chaotic journey. I usually want to share solutions and fixes to problems that i encounter during my work - not with this post unfortunately. Maybe some reader has a better understanding of the topic and can help out with a solution.
</RANT>
Issue Collection
adding some of the issues referenced here in this post - mostly for myself to keep track of them:
i’m already working on my next post about .NET MAUI which will be more positive - just had to get this topic off my chest.