VSCode launch.json to run C# project with dotnet watch / hot reload

804 views Asked by At

I have a dotnet C# project and I like to test my source changes without the need of building and launching the program manually every time. To achieve this I can manually run the program with dotnet watch command in a terminal. But I would also want to be able to easily launch dotnet watch from VSCode by hitting F5 (Start Debugging) and/or Ctrl+F5 (Run Without Debugging).

Solutions tried

First try
First I thought having "args": ["watch"] might do the trick in the launch.json:

    {
        "name": "App1 launch",
        "type": "coreclr",
        "request": "launch",
        "preLaunchTask": "App1 build",
        "program": "${workspaceFolder}/App1/bin/Debug/net7.0/App1.dll",
        "args": ["watch"],
        "cwd": "${workspaceFolder}/App1",
        "stopAtEntry": false,
    },

Results
Having additional argument did not change the behavior. Having "type": "coreclr" executes dotnet exec during launch and ignores the watch argument.

Second try
Next I followed instructions described in the thread https://stackoverflow.com/questions/59830506/how-to-setup-an-auto-watch-run-for-net-core-3-1-projects-using-visual-studio-co and ended up having the following configuration in the launch.json:

    {
        "name": "App1 launch",
        "type": "coreclr",
        "request": "launch",
        "preLaunchTask": "App1 watch",
        "program": "${workspaceFolder}/App1/bin/Debug/net7.0/App1.dll",
        "args": [],
        "cwd": "${workspaceFolder}/App1",
        "stopAtEntry": false,
    },

and the following task in the tasks.json:

    {
        "label": "App1 watch",
        "command": "dotnet",
        "type": "process",
        "args": [
            "watch",
            "run",
            "${workspaceFolder}/App1/App1.csproj",
            "/property:GenerateFullPaths=true",
            "/consoleloggerparameters:NoSummary"
        ],
        "problemMatcher": "$msCompile",
        "options": {
            "cwd": "${workspaceFolder}/App1/"
        },
    },

Results

  1. Task App1 watch runs dotnet watch with hot reload enabled, as expected
  2. The VSCode terminal has the pre-launch task App1 watch awaiting for Ctrl+C, so the actual launch does not happen yet, undesired behavior
  3. After the pre-launch task is manually terminated in the terminal, the App1 launch relaunches the application with "dotnet exec" command, obviously undesired behavior

Conclusion

I also tried several other methods not worth of mentioning here. It seems that at the moment it is impossible to get the desired behavior in VSCode.

So for my own projects I wrote this simple guideline as the easiest work-around:

  1. Open an existing terminal or a new terminal (If you do this in VSCode, note that you can have several terminals open at the same time in VSCode, very handy when working with a multi-project workspace)
  2. Navigate to project folder (in this example to the App1 folder)
  3. In terminal, execute command: dotnet watch
  4. If you want to attach the process (note: this needs to be done before making any changes to the source, otherwise it won't work) in VSCode, you do it by:
    1. choose "Run and Debug" from left menu
    2. Choose from dropdown "App1 Attach"
    3. press Play-button Note that after making source changes, the App1.dll is restarted automatically by the watcher (Hot reload), so you need to reattach the process again :-/
  5. Press Ctrl+C in the terminal when you want to stop running the App1

Above optional step #4 assumes that you have launch.json containing the following configuration:

    {
        "name": "App1 attach",
        "type": "coreclr",
        "request": "attach",
        "processName":"App1.dll"
    },

This work-around also has a downside: When you make source changes, hot reload will restart the application and you need to re-attach it again. But note that you might not need the attaching every time at all. During intense development I survive mostly by following the simple error messages in the terminal and enjoy the fast implement-test iterations which hot reload provides me.

Final words
I decided to write this down for everyone, since I used too many hours for trying to figure out the best solution. It seems that an improved debugger (one that would execute the watch argument properly and would re-attach the process automatically after every hot reload) would be needed for optimal solution. But please let me and others know, if you managed to find a viable solution!

Notes
Above examples assume you have an project named App1 in a folder App1 in your VSCode workspace. launch.json and tasks.json should be stored in the .vscode folder.

In above examples I had the following setup:

  • Visual Studio Code: 1.83.1

  • .NET SDKs installed: 7.0.403

  • .NET runtimes installed:

    • Microsoft.AspNetCore.App 7.0.13

    • Microsoft.NETCore.App 7.0.13

    • Microsoft.WindowsDesktop.App 7.0.13

  • Runtime Environment:

    • OS Name: Windows OS

    • Version: 10.0.22621

0

There are 0 answers