Unhinged way to build .NET WPF applications on Linux
Motivation
I’ve always been a fan of Linux and its open-source ecosystem, and I’ve been using it as my daily driver since 2020. However, there are times when we need to work with Windows-specific frameworks like .NET WPF, which is a UI framework for building desktop applications that is typically used on Windows, as it relies on Windows-specific libraries and technologies, making it a challenge to develop WPF applications on Linux (seemed literally impossible).
Recently, I found myself in a situation where I needed to develop a .NET WPF application, but I didn’t want to switch to Windows just for this project.
I knew that Windows binaries could be run using compatibility layers like Wine or Proton, which are commonly used for gaming on Linux. That’s when an idea struck me: what if I could use Wine not just to run the application, but also to build it?
This unconventional approach sparked my curiosity, and I decided to explore the possibility of building and running .NET WPF applications on Linux using Wine. In this article, I’ll share my journey and the steps I took to make this unorthodox development setup work.
Prerequisites
For this project you will need:
- Wine — https://www.winehq.org
- Winetricks — https://wiki.winehq.org/Winetricks
- Windows version of .NET SDK installed with wine-https://dotnet.microsoft.com/en-us/download
Yes, you will need to download the .exe and install with:
cd Downloads
wine dotnet-sdk-<version>-win-x64.exe
Building the app
Because the way WPF works we can’t just cross compile it, we need to compile it via wine, which is not the best solution, but this is currently the only way it will work:
# linux work directory needs to be mapped for wine
# for instance the project is at \run\media\hunor\exampleProject...
wine cmd /c dotnet publish "Z:\run\media\hunor\exampleProject\exampleProject\exampleProject.csproj" -c Release -r win-x64 --self-contained false && echo "finished building"
# Ialso added an echo at the end for debugging purposes:)
Running the app
For some reason I couldn’t just start the application with:
wine exampleProject.exe
I had to add the following environmental variable in front of it:
DOTNET_ROOT="~/.wine/drive_c/Program Files/dotnet" && wine exampleProject.exe
Additional notes
For making development easier you can create an alias and a function in your .bashrc or .zshrc
alias 'dotnet-wine'='DOTNET_ROOT="~/.wine/drive_c/Program Files/dotnet" && wine'
dotnet-wpf-build() {
local currentPath=$(pwd)
local winePath=$(echo $currentPath | sed 's#/#\\#g' | sed 's#^#Z:\\#')
# Find the first .csproj file in the current directory
local csprojFile=$(find . -maxdepth 1 -name "*.csproj" -print -quit)
if [[ -z "$csprojFile" ]]; then
echo "No .csproj file found in the current directory."
return 1
fi
# Convert Linux path to Windows path format for Wine
local csprojFileName=$(basename "$csprojFile")
local wineCsprojPath=$(echo "$currentPath/$csprojFileName" | sed 's#/#\\#g' | sed 's#^#Z:\\#')
echo "Building $csprojFileName..."
wine cmd /c dotnet publish "$wineCsprojPath" -c Release -r win-x64 --self-contained false
echo "Finished building WPF project:)"
}
This way when you want to compile and run the project you just need to run:
>dotnet-wpf-build
>dotnet-wine ./bin/Release/net<version>-windows/win-x64/exampleProject.exe
Disclaimer
While the method described in this article presents a possible solution for building .NET WPF applications on Linux, I wouldn’t recommend developing and building an app this way for serious projects. During my experience, I primarily used Visual Studio Code (VSCode) for writing the code. Although VSCode offers a .NET extension pack, it still lacks the full range of features and support you would get from a Windows-based IDE, especially when it comes to WPF development. While I had access to basic features like code formatting, syntax highlighting, and .NET Core development assistance, more complex features and XAML-specific support were not available.
It’s important to note that this article and project were undertaken for the purpose of experimentation and curiosity, rather than as a guide for actual production-level development on Linux. As much as I would love for this to be a viable option, the current reality is that if you need to develop .NET WPF applications, using Windows (either through dual-booting or a virtual machine) is still the recommended approach.
If you have the flexibility to choose your development framework, you might want to consider cross-platform .NET UI frameworks such as Avalonia, .NET MAUI, or Uno Platform, which provide better compatibility and tooling support across different operating systems, including Linux.