In this blog post I will show how to remotely debug simple .NET Core console application running on Raspberry Pi and Ubuntu Linux.
The purpose of this blog post is not to debug complex application, but to show step by step procedure how to perform remote debugging of .NET Core application. In other words, I would like to stop remote application execution and checkout execution parameters and call stack.
To start with, my setup looks like this.
My playground specs
My Raspberry Pi specs
- Raspberry Pi 4 B 4GB
- Ubuntu 18.04.3 LTS
- Kernel: Linux 4.19.97-v8-27
- Architecture: arm64
- Latest (as of this writing) .NET Core 3.1
- You can download and check how to install this on Raspberry Pi here: https://dotnet.microsoft.com/download/dotnet-core/thank-you/sdk-3.1.301-linux-arm64-binaries
- Visual Studio .NET Core Debugger aka vsdbg
- You can find detailed instructions here: https://github.com/Microsoft/MIEngine/wiki/Offroad-Debugging-of-.NET-Core-on-Linux—OSX-from-Visual-Studio#linux-computer
And of course, ssh access to this machine.
My Windows 10 development machine specs
- .NET Core 3.1 SDK
- Can be downloaded here: https://dotnet.microsoft.com/download/dotnet-core/thank-you/sdk-3.1.301-windows-x64-installer
- Visual Studio Code
- Small, but useful toolbox for ssh – like scp, ssh, etc…
- Generally only one ssh client tool is needed, only putty is also ok
- Instructions how to use and to install OpenSsh on Windows are here: https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_overview and https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse
- use of plink.exe to automate ssh connection from VS Code
- Putty is awesome ssh and telnet client tool, use it!!
- Link: https://www.putty.org
- C# extension for Visual Studio Code
My simple .NET Core Console app
To demonstrate remote debugging I will create simple .NET Core Console application.
Then, I use my Visual Studio Code and open folder with generated .NET Core Console project.
As you can see, it’s really basic. Let’s add some magic to it.
I will add some code to the application: when console is started, system info is displayed and then inside infinite loop some processing is done, namely: current time is displayed, two random numbers are summed and displayed and finally to slow down everything – sleep the app for 5 secs. Simple, agree?
Further, lets check if everything compiles and if debugging works on my local development Windows machine. I start the app with debugger option on (by hitting F5 key or via menu Run->Start Debugging).
Upper picture clearly shows running app (in debug mode) with breakpoint, local debug variables and application execution output. Local debugging is working as expected.
So, what about remote debugging.
Start remote debugging
First, I need to compile my source code for target architecture (Linux arm64), deploy it to remote system and connect my local development environment to remote debugger.
I compile and publish my simple .NET Core app for my Raspberry Pi with following command:
dotnet publish -r linux-arm64 –self-contained false
One additional note here: I compiled my app with runtime dependent option, meaning that on my target machine I need to have shared runtime enabled and installed. Of course, self-contained build is also possible. You can read my blog post debating .NET Core 3.0 publish options here: https://www.jenx.si/2020/02/05/deployment-options-in-net-core-3-0.
OK, now I have binaries for my PI ready. I will deploy it via ssh to my remote Raspberry Pi. For that purpose I will use scp tool from OpenSsh toolset. I will copy my binaries to my remote Raspberry PI via ssh with following command:
<strong>scp *.* jenx@pi4:/home/jenx/Jenx.RemoteDebug</strong>
Then, I switch to my Raspberry Pi, update file permissions and try my app if it works.
Voila, my app running on my remote Raspberry device as expected.
In the next section, I will show how to enable my Visual Studio Code for remote debugging.
Enable Visual Studio Code for remote debugging.
Currently, I have my code on my local Windows development machine and deployed and running binaries on my remote Pi device. I need to tune up Visual Studio Code to able to attach to my Raspberry Pi and stop application execution at my breakpoint.
Visual Studio generates launch.json inside .vscode folder where I can tune up Launch Targets with debugger settings.
On short, for my presented example my settings for remote debugging is under section named “ .NET Core Debug on my Pi4 (remote) “. All settings are more or less self-explanatory.
"name": ".NET Core Launch (console)",
// removed from brevity....
"name": ".NET Core Debug on my Pi4 (remote)",
When I start app with this debug target – as shown below:
I get this:
Finally, I can debug my .NET Core C# code on my remote Raspberry PI running Ubuntu Linux.
In this blog post I presented step-by-step procedure how to debug .NET Core application running on remote Raspberry Pi running Ubuntu Linux.
The idea was to show how to debug app as simple as possible. Of course, there is a lot of room to improve this procedure. Just to mention few of them: automatic deploy binaries to remote computer at compile time, automate ssh connection by using private/public key (removing passwords in configs), uniforming ssh tools (putty or OpenSsh client tools), etc.
Till next time, happy coding.