Skip to content
Bruno Sonnino
Menu
  • Home
  • About
Menu

Developing for Linux in Windows with C#

Posted on 25 February 2022

Once there was a time where Microsoft and Linux were enemies and who was developing in Windows didn't develop for Linux and vice-versa. Time has passed and things have changed. And how they have changed!

Multi-platform development has evolved, Microsoft released .NET open source, and you can run it both on Linux and Mac (besides Windows, of course). You can use VS Code to develop your code in any of these platforms, and VS Code isn't restricted to .NET Languages: you can develop in Python, Perl or even Clipper/Harbour, Cobol or Fortran. What a change!

Besides that, you can run a Linux distro directly in Windows, with no need of any VM, dual boot or Live CD. The key for that is WSL, the Windows Subsystem for Linux, that allows you to run a full Linux environment, including any Linux application without modification (you can even run Linux graphical apps with WSLg, that's in test - the image below shows GIMP running on Windows)

And, just to make sure, it's not an emulation of Linux. You are running the full distro directly on Windows. WSL uses a translation layer between Linux and Windows, to translate the calls between both OSs and WSL2 uses a Linux kernel for its magic. You can compare both versions of WSL here.

To develop in Linux, the first thing is to get Windows Terminal. This is the successor of the old Windows command line prompt and offers many improvements: customization, tabbed interface and it allows you to use multiple shell types: Windows command, Powershell, Linux prompt or even an Azure Cloud Shell. If you are using Windows 11, you already have it, as it's installed by default. If you are still using Windows 10, you can get it from the Microsoft Store.

Once you have Windows Terminal installed, you must install WSL. Just open a command prompt window and type

wsl --install
Dos

This will install WSL in your machine. If that doesn't work, you will have to install it manually, using the installation steps listed here.

With WSL installed, you need to install your preferred Linux distro. You can get it from the Microsoft Store:

Or you can install it directly from the command prompt. wsl --list lists all the available distros in your machine (you can install and use many distros) and wsl --list --online lists the available distros online:

To install an online distro, you must use

wsl --install -d <Distro>
Dos

If the distro isn't available online or in the store, you still can install it, by getting the appx packages an manually installing it, as described here. One other way is to check if there is an alternate way to install it in WSL. For example, to install Linux Mint, you can go to the LinuxMintWSL Github and download the installer for it.

When you have WLS and the distros installed in your machine, you can click on the down arrow in the Terminal title bar and it will show them in the list, so you can select and open a command prompt for that distro:

The next step is to install dotnet 6.0. To do that, you should follow the instructions for your distro in

For Linux Mint (based on Ubuntu), you should run these commands on the bash prompt:

wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb

sudo apt-get update; \
  sudo apt-get install -y apt-transport-https && \
  sudo apt-get update && \
  sudo apt-get install -y dotnet-sdk-6.0
Bash

Once installed, you can get the installed version with

dotnet --version
Bash

Now, you can create and run a dotnet program in Linux. To show the available app types to create, you can run

dotnet new
Bash

This will list the common templates for a new app. To list all templates, you should use

dotnet new --list
Bash

We can create a new console app using this command:

dotnet new console -o simple-console
Bash

This command will create a new console app in the simple-console folder. We can change to this folder with cd simple-console and run the program with

dotnet run
Bash

This is already great but, unless you are already a VI or Emacs guru (which I am not 😃), you will have some trouble to modify it. I personally, think that the best way to modify a Linux program in WSL is to use VSCode. By typing code . in the command prompt, VS Code server will be downloaded and installed automatically and VSCode will open in your desktop

In this case, you won't have VS Code for Linux running. When you are using VS Code from WSL, something different happens: VS Code will be split into two parts, a server (which runs on Linux) and a client (that runs on Windows). You will be editing the files on Windows, but saving them in Linux. You can see in VS Code status bar, at the bottom WSL: Mint, indicating that we are editing files in WSL. If you open a terminal in VS Code with Ctrl+`, you will see that it's a bash prompt and not a command line or a Powershell prompt.

We can edit program.cs to show the OS version with:

Console.WriteLine($@"Hello World! 
Operating System: {System.Runtime.InteropServices.RuntimeInformation.OSDescription}");
C#

When we save and run the program we will get

This is still great, but I doubt that's what you want to do when your are developing a Linux app. Many times, we'll want to develop a web api to serve our data. For that, we must change to the parent folder and create a new app with

dotnet new webapi -o webapi
Bash

If you change to the webapi folder and run it with dotnet run, you will see the endpoints for the API:

In our case, if we open a browser window and type

https://localhost:7219/swagger
Bash

We will see the swagger interface for our api:

We can test it and see that it works fine:

But we can also use the curl command to get the data. In the bash prompt, we can type

curl -X 'GET' \
  'https://localhost:7219/WeatherForecast' \
  -H 'accept: text/plain'
Bash

to get the api data (I got this command line from the swagget test window). If you do that, you will see a certificate error. We didn't set the certificate for the web site, and we can bypass that with the -k flag:

curl -k -X 'GET' \
  'https://localhost:7219/WeatherForecast' \
  -H 'accept: text/plain'
Bash

As you can see, we are getting the json data for the weather forecast sample. You can still consume the api from our console app. All we have to do is change the program.cs file to

using System.Text.Json;

var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
              (message, cert, chain, errors) => 
              { return true; };
using var client = new HttpClient(handler);
var json = await client.GetStringAsync("https://localhost:7219/weatherforecast");
var forecasts = JsonSerializer.Deserialize<List<WeatherForecast>>(json);
if (forecasts == null)
    return;
foreach (var forecast in forecasts)
    Console.WriteLine($"{forecast.date:dd/MM/yyyy}  {forecast.temperatureC}  {forecast.summary}");

public class WeatherForecast
{
    public DateTime date { get; set; }
    public int temperatureC { get; set; }
    public int temperatureF => 32 + (int)(temperatureC / 0.5556);
    public string? summary { get; set; }
} 
C#

If you run the program, you will see something like this:

We are consuming the API from our console program in Linux, but we are running .NET, we can run the same program in Windows. One nice thing in WSL is that we can run Windows apps from Linux. If you type

explorer.exe .
Bash

It will open Windows Explorer with the current path open. If you copy the address in the address bar, you will see:

\\wsl.localhost\Mint\home\bruno\LinuxProg\simple-console

As you can see, the Linux folder is considered a new network. We can map the drive in Windows to use it, with a command like this one:

net use y: \\wsl.localhost\Mint
Bash

If you open a command prompt and type this command, you will have the y: drive available to use. You can then change to the program folder and type dotnet run to run the same program in Windows. If you do that, you will see that we can run the same program we've created in Linux in the Windows command prompt and consume the API that is still running in Linux.

As you can see, with .NET you can run the same program in Linux or in Windows and you can interact with the APIs that are running in Linux. You will be using the tools that you still know. You can even access one file system from the other seamlessly (the Windows file system is mounted in /mnt/c/ in Linux). You will be using the same C# language that you know and, most of the time, you don't even need to know Linux APIs - .NET will take care of that for you.

The full code of this article will be in https://github.com/bsonnino/LinuxProg

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • May 2025
  • December 2024
  • October 2024
  • August 2024
  • July 2024
  • June 2024
  • November 2023
  • October 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • June 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • July 2021
  • June 2021
  • May 2021
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • October 2020
  • September 2020
  • April 2020
  • March 2020
  • January 2020
  • November 2019
  • September 2019
  • August 2019
  • July 2019
  • June 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • November 2017
  • October 2017
  • September 2017
  • August 2017
  • June 2017
  • May 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • February 2016
  • October 2015
  • August 2013
  • May 2013
  • February 2012
  • January 2012
  • April 2011
  • March 2011
  • December 2010
  • November 2009
  • June 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • July 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • Development
  • English
  • Português
  • Uncategorized
  • Windows

.NET AI Algorithms asp.NET Backup C# Debugging Delphi Dependency Injection Desktop Bridge Desktop icons Entity Framework JSON Linq Mef Minimal API MVVM NTFS Open Source OpenXML OzCode PowerShell Sensors Silverlight Source Code Generators sql server Surface Dial Testing Tools TypeScript UI Unit Testing UWP Visual Studio VS Code WCF WebView2 WinAppSDK Windows Windows 10 Windows Forms Windows Phone WPF XAML Zip

  • Entries RSS
  • Comments RSS
©2025 Bruno Sonnino | Design: Newspaperly WordPress Theme
Menu
  • Home
  • About