Linux .NET remote debugging from Visual Studio

I found this Visual Studio 2015 extension which works like a charm: MonoRemoteDebugger for Visual Studio 2015

See MonoRemoteDebugger v1.0.4 to fix conflict with Xamarin Visual Studio extension on Visual Studio 2015 update2.


I have finally found a good way to perform remote debugging of C# code running on my Raspberry Pi. I have switched from Mono to .NET Core and can now use Visual Studio to debug code running on the Raspberry Pi almost as easy as when running on my development machine.

The following steps were tested using Windows 10 version 1909, Visual Studio 2019 version 16.4.3, Raspbian Buster Lite version 2020-02-13 and a Raspberry Pi 2 Model B. .NET Core requires an ARMv7 CPU, so it will not run on Raspberry Pi 1 and Zero.

  1. Go to https://dotnet.microsoft.com/download/dotnet-core and select .NET Core 3.1 (or later). Click the link for Linux ARM32 runtime binaries and copy the direct link displayed on the next page. (Do not right-click the ARM32 link and select copy link address, as you will end up with a webpage if you download that link.)

    .NET Core download website

  2. Open a SSH session to the Raspberry Pi, download and install the binaries:

    ssh [email protected]
    wget https://download.visualstudio.microsoft.com/download/pr/c11e9248-404f-4e5b-bd99-175079419d6f/83902a43e06f9fb4e45a4c6a6d5afc0b/dotnet-runtime-3.1.3-linux-arm.tar.gz
    sudo mkdir /opt/dotnet
    sudo tar zxf dotnet-runtime-3.1.3-linux-arm.tar.gz -C /opt/dotnet
    sudo ln -s /opt/dotnet/dotnet /usr/bin/dotnet
    
  3. Add the following line to ~/.bashrc, logout and login again to activate:

    export DOTNET_ROOT=/opt/dotnet
    
  4. Check that .NET Core has been installed correctly:

    dotnet --info
    

    Output from dotnet --info

  5. Create a *.NET Core Console App```lang-none in Visual Studio. Set Target framework = .NET Core 3.1 (or the version you downloaded to the Raspberry Pi). Make sure that Project → Properties → Build → Output → Advanced → Debugging information = Portable.

    Advanced build settings

  6. Build the project in Visual Studio and copy all *.dll, *.pdb, *.deps.json and *.runtimeconfig.json files from the development machine to the Pi. PuTTY's pscp command can be used:

    cd bin\Debug\netcoreapp3.1
    pscp -pw <password> *.dll *.pdb *.deps.json *.runtimeconfig.json [email protected]:/home/pi
    
  7. Open a SSH session to the Raspberry Pi and run the program, or start it from the development machine using SSH:

    ssh [email protected] dotnet /home/pi/MyProgram.dll
    
  8. Attach to the remote process by selecting the Debug → Attach to Process menu item in Visual Studio. Select Connection type = SSH and in the Connection target textbox, type [email protected] and press Enter.

    Connection target

  9. Enter password and click the Connect button.

    Connect window

  10. Click the Select button.

    Attach to process image

  11. Select Managed (.NET Core for Unix) and click the OK button.

    Select code type

  12. Select the dotnet MyProgram.dll process and click the Attach button. The first connection might take several minutes, but subsequent connections are much faster.

Enjoy setting breakpoints, adding watches, stepping through code and even using "Set Next Statement" - almost as fast as when debugging on the local machine. The only thing I'm missing so far is Edit and Continue, but not enough to investigate if it is possible to achieve.


I found this guide explaining how to perform remote debugging on Linux, from Windows, using Xamarin Studio which is now free except for iOS & Android development. I've expanded it with fixes for the problems I encountered while testing it on a Raspberry Pi Zero W running Raspbian Jessie Lite (2017-04-10).

  1. Download and install Xamarin Studio, GTK# for .NET and .NET Framework 4.6.2. Xamarin Studio requires .NET 4.5 but GTK# requires .NET 4.6. I used Xamarin Studio version 6.1.2 (build 44) and GTK# version 2.12.44.
  2. I installed Xamarin Studio on a virtual machine different from my VS2015 machine, so I needed to download and install MSBuild Tools 2013 and MSBuild Tools 2015 as well.
  3. Create an environment variable MONODEVELOP_SDB_TEST = 1 (My Computer -> Properties -> Advanced System Settings -> Environment Variables).
  4. Start Xamarin Studio. If no window is shown, check the log files in the folder %localappdata%\XamarinStudio-6.0\Logs to see what failed.
  5. I created a .NET 4.6 Console Application in Visual Studio 2015 and added the NuGet package Mono.Unofficial.pdb2mdb, I used version 4.2.3.4. The package Mono.pdb2mdb version 0.1.0.20130128 does not seem to work with assemblies built by VS2015 (PdbDebugException: Unknown custom metadata item kind: 6).
  6. Load the .sln or .csproj file from Visual Studio into Xamarin Studio. Build the solution and use the pdb2mdb tool from the NuGet packages folder to create a .mdb file: pdb2mdb MyProgram.exe
  7. I used WinSCP to copy MyProgram.exe and MyProgram.exe.mdb to my Raspberry Pi.
  8. I logged in with Putty using SSH and installed Mono version 3.2.8 on the Pi: sudo apt-get install mono-complete.
  9. Start the Mono runtime with debugger flags: mono --debug --debugger-agent=transport=dt_socket,address=0.0.0.0:12345,server=y /path/to/MyProgram.exe. This will start the program but halt execution until the Xamarin Studio debugger has connected.
  10. Set a breakpoint in Xamarin Studio and select the menu item Run -> Run with -> Custom Configuration... and select Run Action = Debug - Custom Command Mono Soft Debugger. Click Debug.
  11. Fill in the IP and Port fields with the IP address of your linux system and port 12345 as specified in the Mono command line. Click Connect and execution will begin, stopping at the breakpoint set.

Screenshot of Xamarin Studio Debugging

It is possible to set conditional breakpoints, step into/out of/over code, watch primitives and objects etc and it's quite fast as well. I'd rather debug directly from Visual Studio, but this seems like a fully working solution.