Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)


:P
On this page:

The Windows Subsystem for Linux (WSL), also known as Bash on Ubuntu for Windows makes it very easy to get your feet wet with Linux on Windows 10 without having to set up Virtual machines or installing any software to get Linux up and running. Check out Scott Hanselman's excellent post today (as I'm writing this) on some of the developer features of the WSL shell. In fact, it was a few tweets from Scott yesterday that prompted me to play around with WSL and .NET Core today and write this post.

What's WSL?

WSL is a built in feature of Windows 10 (Anniversary Update and later) that's always available by simply typing Bash into the Start menu. You get a Bash command prompt:

From here you have access to a headless Ubuntu (14.04 or 16.04 with Creators Update) instance with a full Linux file system and access to the host network connection and other hardware.

WSL is not a VM - if you open Hyper-V manager in Windows there's nothing running. Rather WSL is a custom implementation of the Linux shell that natively maps Linux api and commands to Windows, and executes them using standard Linux command line tools. This sounds like it'd be very buggy but it appears that this is working very well indeed - well enough in fact to execute a dotnet Web application in the subsystem as I'll show in this post.

Accessing Windows Files From Linux

WSL can access the Windows File System using a special drive mount:

/mnt/c/

gets you to the Windows C drive and from there the entire disk is available. All drives are mapped this way.

Opening Bash in any Windows Folder: Type Bash

In fact you can open a Windows Command or PowerShell prompt anywhere on your local drive, simply type Bash and be in that folder in the Bash Linux shell:

The shell loads in the active Windows folder and I can run all commands that are in scope of that folder. Here I'm displaying the Ubuntu version using lsb_release -a.

Note that exit puts me right back into Powershell, but if I changed folders in Bash the PS shell will not reflect the change when I get back - ie. the original shell's scope is preserved as you would expect.

Access Linux Files from Windows: Look but don't touch!

You can also look at the Linux file system from Windows at:

C:\Users\<user>\AppData\Local\lxss\rootfs

but it's very important that you don't change files on the Linux Partition from Windows.

I didn't know this and promptly modified files with an editor from Windows, only to see them show up in the Windows Explorer, but not with actual Linux file listings which means the directory table is actually corrupted for that folder I was working in. Clearly not a good idea.

Moral of the story:

  • It's Ok to modify Windows files from WSL
  • It's not Ok to modify Linux files from Windows

This is a bummer, but not as big of a deal as you might think - you can happily work with and modify data on your Windows drives and access those from the Bash shell. It's also nice in that you can use your existing Windows project folders for any .NET Core applications - there's no need to copy files around between the two platforms. You can of course still do that - if you rather use Git to completely restore files on the Linux instance and explicitly work of Linux folders. Just keep in mind that you can't easily edit files using a decent editor from Window - you're more or less limited to command line tools available inside of the headless Linux instance.

Using dotnet Command Line Tools in WSL

So let's see if we can create a .NET application in the Bash shell for Windows.

The first step is:

  • Install the .NET SDK for Linux

Go to dot.net for Linux/Ubuntu and follow the installation instructions there.

To find out the Ubuntu version running, use this command:

lsb_release -a

and then follow the rest of the install instruction on the SDK installation page.

dotnet new in WSL

With the SDK installed you can now use the dotnet command line tooling to create new projects, build, publish and so on.

To create a new project do this:

  • Start the Bash shell from the Start Menu
  • Navigate and create a folder for your project. For example: cd /mnt/c/Temp/projects/consoleapp
  • dotnet new console
  • dotnet restore
  • dotnet run

Here's what all this looks like in the Bash Shell:

Running dotnet new from Windows Bash Shell for Linux

Just to prove that this is really Linux that's running the application and we can change the code easily from Windows with any editor, let's edit the Program.cs source file to the following:

using System;

namespace consoleapp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World! "  + 
                  System.Runtime.InteropServices.RuntimeInformation.OSDescription);
        }
    }
}

Then do:

dotnet run

from the command line and you get:

Display Linux version in .NET Core Console App

Schweet!

Running ASP.NET

The code above is obviously very simple so you'd expect that to work, but what about something a little more realistic?

I have an ASP.NET Core AlbumViewer application that is a bit more real world in that it accesses a database, deals with authentication and various ASP.NET support features. This application lives in a Windows folder, but using the Linux Bash shell I can just navigate to that project folder and then run the application out of that folder.

To try this out yourself you can clone the Repo from here:

Make sure it works under Windows before trying the Linux Bash Shell.

Assuming the app works I can now do the following:

  • Open the Windows Bash Shell
  • Navigate to the Web project folder (cd /mnt/c/projects/AlbumViewerVNext/src/AlbumViewerNetCore)
  • dotnet restore
  • dotnet run

And this should just work:

The app fires right up and just like on Windows serves requests on port 5000. No changes it just works, and I have an app that's running under Linux. Heck I could even fire up the same application under Windows on a different port at the same time.

Say Whaaat?

And there you have it - a .NET console app running under the Linux subsystem in Windows. No VMs, no complicated setup - the subsystem is just always available to you and it's a relatively painless way to experiment with running your .NET Core applications under Linux without having to set up anything special.

Ok, I know - NodeJs has done that for many years, but seeing this work with .NET is still pretty exciting. And having an easy way to test an application under Linux with the Bash for Windows shell without having to set up a VM is a really nice addition to Windows as a Developer Platform.

You can check to see if things break running under Linux (subtle differences in features, apis and file naming for example) and generally see how things work. The application has full access to the Linux OS including the file system (unlike the Windows shell) so as far as the app is concerned it's native on Linux.

Given that Microsoft states this is not a ‘full’ version of Linux it's pretty impressive that you can run a relatively full featured Web application without a hiccup is very promising for this tech.

You should understand that WSL is a developer feature of Windows 10. It doesn't exist on server OS versions and so this is meant as a helpful tool for developers. It's not a replacement for deploying a .NET Core application on proper Linux VM or running an application under Docker. FWIW, it might also be possible to run Docker under WSL and bypass the need for a separate Alpine VM running in Hyper-V. I haven't tried this but it's something worth checking out which would be a nice way to test Docker installs locally on ‘native’ Linux. If this doesn't work yet, I suspect this is part of the greater plan for Microsoft of integrating the Windows and Linux more smoothly at least on a developer machine. Maybe somebody's tried this out - if so please chime in in the comments.

Anyways, give the Windows Subsystem for Linux a spin with your .NET Core apps - it's easy enough to get started with and is an easy way to ease into familiarizing yourself with Linux. And I know that can be slow going - I'm still struggling with it, but anything that makes it easier helps!

Resources

this post created with Markdown Monster
Posted in ASP.NET  ASP.NET  Linux  

The Voices of Reason


 

Janne Rantala
April 14, 2017

# re: Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)

I was also interested to see if I was able to run Docker in WSL. Command "Docker" replied that Docker wasn't found. I don't remember what was the exact error I got, but that was what it was implying. Installing Docker with apt-get however said that docker was already installed. Haven't tried with creator's update yet to see if things have changed though.


Rick Strahl
April 14, 2017

# re: Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)

@Janne - did you install docker from their Web site. I think you might need a full install and follow the install Docker instructions there. I haven't looked at this but will probably over the weekend.


Matthew Blott
April 14, 2017

# re: Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)

I saw your comment under Hanselman's post which piqued my interest - nice write up! I agree Linux can be a bit overwhelming to newcomers - I've been using it regularly for a couple of years now and wish there was something like WSL when I started. As I said in my comment under Hanselman's post, there are a lot of really convenient features built into Linux, it's well worth the effort getting familiar with it.


Jeff Ferguson
April 14, 2017

# re: Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)

Is it currently possible (or is it on a roadmap) to call into .NET Core assemblies from a Bash script in WSL? In other words, can I develop a Bash script that creates .NET Core objects and calls methods on those objects like I can do to today in Powershell?


Andrey Grishin
April 14, 2017

# re: Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)

I'm trying this new feature. It works but performance is horribly slow compared to running netcore on Windows.

WSL:

agrishin@AGRISHIN:/mnt/c/Sources/grishin/mytestapp$ time dotnet run
Hello World!

real    0m29.473s
user    0m8.047s
sys     0m27.078s

Git Bash (running with Windows dotnet):

Andrey@AGRISHIN MINGW64 /c/Sources/grishin/mytestapp
$ time dotnet run
Hello World!

real    0m5.600s
user    0m0.015s
sys     0m0.015s

I also tried to edit .cs files with VSCode but again without luck. Editor autocompletion breaks after package restore in WSL. So it looks promising but unusable for now. (I'm using fresh Creators Update Windows)


Rick Strahl
April 14, 2017

# re: Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)

@Jeff - No - there's no automation model for this. I don't think you can do this in Powershell with .NET Core either - only classic .NET components. Powershell understands .NET so it can load assemblies, but Bash - not so much, it's a text based interface. So pretty sure the answer to this is no. But didn't I hear that Powershell is being ported to run on Linux? https://github.com/PowerShell/PowerShell @Andrey - I'm not surprised that perf is not all that great. After all WSL is basically an emulator that forwards calls. But this isn't meant as a production feature - it's a developer convenience feature. OTOH, I was testing perf in Docker (with stock Alpine VM in Hyper-V) a few days ago and perf in that scenario is also terrible compared to native Windows. To be fair I didn't optimize anything, but it was pretty sad compared to native, close to what you show here.


Matthew Blott
April 14, 2017

# re: Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)

@Jeff

You can't do that and I wouldn't expect you to be able to. You can't call objects in Ruby, Python, Java or any other language from bash - it would be like calling .NET objects from the standard Windows terminal. PowerShell is a .NET program itself which is why you're able to interact easily with .NET objects. That said I work pretty much full time with Mono and regularly call C# code from bash (actually zsh but it's much the same thing) with a simple ...


mono app.exe $some_environement_variable

... in my bash scripts. There's nothing to stop you creating an API to expose the methods you want to call and doing the same thing.


Rick Strahl
April 14, 2017

# re: Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)

@Matthew, @Jeff - There's also ScriptCs which will allow you to use C# code to automate tasks and also call into .NET components. I believe it works with .NET Core as well now.


Dennis
September 05, 2018

# re: Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)

One remark about performance of dotnet core in WSL vs. "bare-metal" Windows 10:

The dotnet core linux interpreter (when running inside the WSL) is indeed horribly slow, but if you build your application with the -r switch, you get a compiled executable, which runs comparably fast on WSL and Windows 10. List of RIDs: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog

dotnet build -r linux-x64

dotnet build -r win10-x64

you can even cross-compile like this, and create an EXE using dotnet core in WSL that is executable in windows.

best regards, Dennis


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024