Getting started with cross-platform development using .NET on Ubuntu on WSL

haydenb

on 3 June 2020

.NET is an open source software framework for building cross-platform applications on Linux, Windows, and macOS. Ubuntu on WSL allows you to build and test applications for Ubuntu and Windows simultaneously. What happens when we mix these together? This blog will demonstrate how to install a .NET development stack on WSL, build a simple OS-aware application, and then test it on both Linux and Windows.

Enable WSL 1

In PowerShell as Administrator run:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

If you are installing just WSL 1, you can restart and skip the next step.

Restart-Computer

If you are installing WSL 2, do not restart, continue to the next step:

Enable WSL 2 (Windows 10 2004+)

See “Ubuntu on WSL 2 Is Generally Available” for more details on Ubuntu on WSL 2.

In PowerShell as Administrator run:

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

and then restart Windows:

Restart-Computer

Install Ubuntu on WSL

Download Ubuntu from the Microsoft Store:

For more ways to install Ubuntu on WSL, see the Ubuntu on WSL wiki page.

Install Windows Terminal

Download the Windows Terminal from the Microsoft Store:

Windows Terminal can also be downloaded from GitHub.

Run Ubuntu on WSL

Open Windows Terminal in PowerShell and run:

ubuntu.exe

When you run Ubuntu on WSL for the first time it will install and then you will create a Linux user. This is separate from your Windows user.

Exit and re-open Windows Terminal and you will find Ubuntu on the drop-down:

You can set Ubuntu as the default and configure Windows Terminal in settings.json.

Update Ubuntu on WSL

You should periodically check for updates and run upgrades on Ubuntu on WSL. We do this with apt, the Ubuntu package manager.

To check for updates run:

sudo apt update

To get upgrades run:

sudo apt upgrade

You can automatically update and apply any available upgrades in the same line by joining them with $& and adding the -y flag:

sudo apt update && sudo apt upgrade -y

Add Microsoft’s .NET repository and signing key

We need to add Microsoft’s .NET repository and signing key to apt. We will download and install a package from Microsoft that will do this.

Make sure you are installing the correct repo for your version of Ubuntu. You can check your current version of Ubuntu with:

cat /etc/os-release

The example below uses Ubuntu 20.04, the latest LTS release from Canonical. If you are still using Ubuntu 16.04, 18.04, or 19.10, you can find the corresponding repos in the Microsoft docs. To learn more about the differences between LTS and interim releases, we have a release cycle page.

Download the Microsoft repository and key package for 20.04:

wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb

Install the Microsoft repo package manually using dpg -i:

sudo dpkg -i packages-microsoft-prod.deb

Now when you update apt you will see the Microsoft repository is checked for upgrades:

Install the .NET SDK

Install the .NET and related dependencies using apt from the Microsoft repository:

sudo apt-get install dotnet-sdk-3.1 -y

Create a workspace

Create a new directory for to work in and change to that directory:

mkdir dotnetproject
cd dotnetproject/

Create a new .NET project

Create a new .NET console project using dotnet new. This will create a file called Program.cs and other necessary folders and files:

dotnet new console

Explore our .NET app

List the files in your new .NET project:

ls

View the contents of Program.cs:

cat Program.cs

Run the sample program:

dotnet run

Customize our .NET app

Open Program.cs in your favorite editor: vi, nano, emacs, or Code with the remote WSL extension:

For our purposes, we will use nano, which is included with Ubuntu on WSL:

nano Program.cs

First we add the Interop services namespace:

using System.Runtime.InteropServices;

Then replace:

Console.WriteLine("Hello World!");

With:

Console.WriteLine($"Hello {System.Environment.GetEnvironmentVariable("USER")}");

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
 {
  Console.WriteLine("We're on Linux!");
 }

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
 {
  Console.WriteLine("We're on Windows!");
 }

Console.WriteLine("Version {0}", Environment.OSVersion.Version);

This code is also available here.

This application tells us our current user, checks if we are on Windows or Linux, and then gives the OS kernel version.

Exit and save and run with:

dotnet run

Make our .NET application cross-platform

We need to update our .NET project file, dotnetproject.csproj, to tell .NET to build for both Linux and Windows.

Open dotnetproject.csproj in our editor and add:

 <PropertyGroup>
    <RuntimeIdentifiers>win10-x64;linux-x64</RuntimeIdentifiers>
 </PropertyGroup>

This directs .NET to build self-contained binaries for both Windows 10 x64 and Linux x64.

Build our cross-platform application

Once our project is properly configured, building our .NET application is as simple as:

dotnet publish -r win10-x64
dotnet publish -r linux-x64

Self-contained binaries for each platform with all required libraries can be found in the project’s /bin/ folder:

ls bin/Debug/netcoreapp3.1/

Test Linux build

You can run your Linux binary direct as follows:

./bin/Debug/netcoreapp3.1/linux-x64/publish/dotnetproject

Test Windows build

To run the Windows build, copy it to your Windows file system:

cp -r ~/dotnetproject/bin/Debug/netcoreapp3.1/win10-x64/publish /mnt/c/Users/Hayden/OneDrive/Desktop/

Then run:

/mnt/c/Users/Hayden/OneDrive/Desktop/publish/dotnetproject.exe

We have built and run the same application for both Linux and Windows. We can test them both simultaneously using WSL.

More Resources for .NET

Ubuntu desktop

Learn how the Ubuntu desktop operating system powers millions of PCs and laptops around the world.

Newsletter signup

Select topics you’re
interested in

In submitting this form, I confirm that I have read and agree to Canonical’s Privacy Notice and Privacy Policy.

Related posts

Canonical Developer Advocate Named Microsoft MVP

We would like to congratulate Hayden Barnes, a Developer Advocate at Canonical for Ubuntu on WSL, who was awarded MVP (Most Valuable Professional) by...

Getting started with CUDA on Ubuntu on WSL 2

At Build 2020 Microsoft announced support for GPU compute on Windows Subsystem for Linux 2. Ubuntu is the leading Linux distribution for WSL and a sponsor of...

Ubuntu at the Microsoft European Virtual Open Source Summit

Event overview and main themes On June 16th 2020, the Microsoft European Virtual Open Source Summit will be the occasion to meet and hear from all the...