C# Custom Build & Debug — VS Code ExtensionA VS Code extension that provides a smooth, zero-prompt build / run / debug workflow for C# (.NET) projects. It auto-detects your compiled output, auto-builds before debug/run, surfaces compiler errors directly in the Problems panel, and delegates the actual debug session to the official C# extension's Table of Contents
Requirements
Installation
ActivationThe extension activates automatically when your workspace contains:
Quick Start
That's it — no FeaturesAuto-Build Before Debug / RunBy default the extension builds your project automatically before every debug or run operation. You never need to manually build first. If the build fails, the debug session is cancelled and errors appear in the Problems panel. Executable Auto-DetectionThe extension searches for your compiled output in this order:
It reads Problems Panel IntegrationBuild errors and warnings are parsed from Zero-Prompt Workflow
Run Modes
Keyboard Shortcuts
All CommandsAccess these via the Command Palette (
You can also right-click any Settings ReferenceOpen VS Code Settings (
Example: workspace settings (
|
| Field | Description |
|---|---|
targetFramework |
Overrides auto-detection; used to select the right bin/Debug/net* subfolder |
configuration |
Debug or Release |
workingDirectory |
Working directory for the launched process |
environmentVariables |
Environment variables injected at debug/run time |
stopAtEntry |
If true, execution pauses at the first line of Main |
justMyCode |
If true, the debugger skips framework and library code |
Debug Walkthrough — Step by Step
This section shows a complete end-to-end debug session using a real buggy C# program.
1. Create the sample project
dotnet new console -n SquareApp
cd SquareApp
Replace Program.cs with:
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter a number:");
int num = int.Parse(Console.ReadLine());
int result = CalculateSquare(num);
Console.WriteLine("Square is: " + result);
}
static int CalculateSquare(int n)
{
// BUG: should be n * n
return n * 2;
}
}
2. Open in VS Code (with the extension active)
# Development mode (no install needed):
code --extensionDevelopmentPath=/path/to/custom-vscode-extension-project-1 /path/to/SquareApp
# Or open normally if the extension is installed:
code /path/to/SquareApp
3. Set a breakpoint
Click in the gutter (the grey area to the left of line numbers) on line 18 — return n * 2;
A red dot appears:
17 static int CalculateSquare(int n)
18 {
19 ● return n * 2; ← red dot = breakpoint
20 }
4. Press F5 to start debugging
The extension automatically:
- Runs
dotnet build(watch the Output panel →C# Custom Build & Debug) - Finds
bin/Debug/net*/SquareApp.dll - Launches a
coreclrdebug session
The integrated terminal opens and shows:
Enter a number:
5. Enter input and hit the breakpoint
Type 5 and press Enter. Execution pauses on the breakpoint line.
The VS Code debug UI activates:
VARIABLES
└─ LOCALS
└─ n = 5 ← the value you passed in
6. Inspect the bug
Click the Debug Console tab at the bottom. Type these expressions and press Enter:
n * 2 → 10 (what the code returns — WRONG for a "square")
n * n → 25 (the correct square of 5)
The bug is confirmed: return n * 2 multiplies by 2 instead of squaring.
7. Fix the bug
Press Shift+F5 to stop. Edit line 19:
// Before:
return n * 2;
// After:
return n * n;
8. Verify the fix
Press F5 again. The extension auto-rebuilds with the fix. Type 5:
Enter a number:
5
Square is: 25 ← correct!
Debug Panel Reference
| Panel | What to use it for |
|---|---|
| Variables | Inspect local variables and their values when paused |
| Watch | Add expressions (e.g. n * n) to track continuously |
| Call Stack | See the chain of method calls that led to the breakpoint |
| Breakpoints | Enable/disable/remove breakpoints centrally |
| Debug Console | Evaluate arbitrary expressions in the paused context |
| Output (C# Custom Build & Debug) | Build logs, session start/stop messages |
| Terminal | Interactive stdin/stdout for your running program |
Breakpoint types
Right-click any breakpoint dot to access advanced options:
- Conditional breakpoint — only pause when
n > 3 - Hit count breakpoint — only pause on the 5th hit
- Logpoint — print a message without pausing (e.g.
"n={n}")
launch.json Integration
No launch.json is required — F5 works out of the box. If you want to customise the debug configuration, create .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "csharp-custom",
"request": "launch",
"name": "Debug C# Project",
"stopAtEntry": false,
"justMyCode": true,
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
]
}
The extension transforms "type": "csharp-custom" into a full coreclr configuration automatically, filling in the program path, args, cwd, and env from your settings.
Status Bar
Three items appear at the bottom of the VS Code window:
| Item | States |
|---|---|
| Build | Idle → In Progress (spinner) → Success (✓) → Error (✗) |
| Run | Idle → In Progress → Success → Error |
| Debug | Idle → Active → Error |
Click any status bar item to run the corresponding command.
Problems Panel (Build Diagnostics)
After every build, the extension parses dotnet build output and populates View → Problems (Ctrl+Shift+M) with clickable diagnostics.
Program.cs line 19 error CS1002: ; expected [C# Build]
Program.cs line 22 warning CS0219: variable 'x' is assigned but never used
Clicking an entry jumps directly to that line. Diagnostics are cleared at the start of each new build.
Attach to Running Process
- Start your .NET application separately (e.g.
dotnet runin a terminal) - Open the Command Palette and run C# Custom: Attach to .NET Process
- A list of running .NET processes appears — select yours
- The debugger attaches and you can set breakpoints immediately
Works on macOS, Linux (uses ps), and Windows (uses wmic).
Troubleshooting
"No compiled executable found"
The executable search failed. Possible causes:
- Project has never been built — press
Cmd+Shift+Bto build manually - The
bin/folder is in a non-standard location — setcsharpCustom.outputPathin settings autoBuildBeforeDebugisfalseand the build is stale
"Failed to start debug session"
The coreclr adapter could not start. Check:
- The C# extension (
ms-dotnettools.csharp) is installed and enabled - Your project builds without errors
- Enable verbose logging (
csharpCustom.enableVerboseLogging: true) and check the Output channel for the full resolved configuration
Build errors not appearing in Problems panel
- Check the Output channel for raw
dotnet buildoutput - Verify the error line format matches
filename(line,col): error|warning CODE: message - MSBuild errors from
.targetsfiles may not include a file path — these will not appear as clickable diagnostics
"dotnet: command not found"
Set the full path: "csharpCustom.dotnetPath": "/usr/local/share/dotnet/dotnet" in settings, or run C# Custom: Validate Environment to diagnose.
Extension not activating
The extension only activates when the workspace contains .cs, .csproj, or .sln files, or when a C# file is opened. Open such a file and the extension will activate.
Verbose logging
Turn on csharpCustom.enableVerboseLogging to see every command the extension runs and the full resolved debug configuration. Check View → Output → C# Custom Build & Debug.
Development & Contributing
Setup
git clone <repo-url>
cd custom-vscode-extension-project-1
npm install
npm run compile
Dev loop
- Open the project in VS Code
- Press F5 — the Extension Development Host opens with your extension loaded
- Edit source files in
src/ - Run
npm run compile(ornpm run watchfor continuous compilation) - Press
Ctrl+R/Cmd+Rin the Extension Development Host to reload
Scripts
npm run compile # TypeScript → out/
npm run watch # Watch mode compile
npm run lint # ESLint (zero errors expected)
npm run pretest # compile + lint
npm test # Run extension tests
npx vsce package # Build .vsix for distribution
Installing locally
npx vsce package
code --install-extension csharp-custom-debugger-1.0.0.vsix
Architecture
All logic is split into single-responsibility manager classes wired together in src/extension.ts via constructor injection. extension.ts only registers commands and subscriptions.
| Class | File | Responsibility |
|---|---|---|
OutputChannelManager |
src/outputChannelManager.ts | VS Code output channel; all log output routes here |
ConfigurationManager |
src/configurationManager.ts | Merges VS Code settings + .vscode/csharp-custom.json; auto-detects target framework from .csproj |
ErrorHandler |
src/errorHandler.ts | In-memory error history, user notifications, .NET CLI validation |
StatusBarManager |
src/statusBarManager.ts | Three status bar items (Build / Run / Debug) with transient state |
BuildManager |
src/buildManager.ts | Spawns dotnet build / clean / restore; populates Problems panel via DiagnosticCollection |
RunManager |
src/runManager.ts | Spawns compiled .dll or .exe in terminal or output channel |
DebugManager |
src/debugManager.ts | Implements DebugConfigurationProvider; transforms csharp-custom → coreclr; process attachment |
Configuration layering
ConfigurationManager reads from two sources (project JSON wins for keys it defines):
- VS Code settings —
csharpCustom.*workspace or global settings .vscode/csharp-custom.json— per-project JSON created by the Configure command
Debug flow
User presses F5
│
▼
resolveDebugConfiguration() ← DebugManager
│
├─ autoBuildBeforeDebug? → csharpCustom.build command
│
├─ find executable:
│ parse <TargetFramework> from .csproj
│ search bin/Debug/<framework>/*.dll
│
├─ build DebugConfiguration { type: "coreclr", program, args, cwd, env, … }
│
└─ return config → VS Code hands to coreclr adapter (C# extension)
│
▼
Full debug session with breakpoints,
watches, call stack, Debug Console
License
MIT — see LICENSE for details.
Changelog
See CHANGELOG.md for a history of changes.