Startup project and solution configuration (Debug|x64, Test|x64, ...) in the status bar, with build and debug tasks that pass both configuration and platform. Made for DotRush, whose build never passes -p:Platform and whose status item shows the configuration but not the project. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0169iPWwKHZoBTNN9qwXiwqk
7.2 KiB
.NET Solution Launcher
Startup project and solution configuration in the status bar, with build and debug that
actually use them. Built for DotRush, next to
the .NET Hot Reload extension in this repo.
$(project) MyGame.Editor $(settings-gear) Test | x64 $(debug-alt)
- The project item shows which
.csprojis the startup project, and picks another one from the executables in the solution (Runtime is a library, so it is not offered). - The configuration item shows the solution configuration —
Debug | x64,Test | x64,Release | Any CPU— exactly asMyGame.slnlists them. - The debug button builds with that configuration and launches the startup project.
Why, when DotRush already has a status bar item
DotRush shows Debug | net10.0. Two things are missing from that:
-
The project name. It is in the tooltip only. With three executables in the solution (Builder, Editor, and whatever comes next) that is the thing you need to see.
-
The platform. DotRush's build task runs
dotnet build <project> -p:Configuration=Xwith no-p:Platform. MSBuild then defaults toAnyCPU, and every property group conditioned on'$(Configuration)|$(Platform)' == 'Debug|x64'is skipped. In this solution that is not cosmetic:MyGame.Runtime, Configuration=DebugDefineConstantswithout -p:Platform(what DotRush runs)TRACE;DEBUGwith -p:Platform=x64TRACE;LOG_INFO;PROFILING;DEBUGSo logging and profiling silently vanish,
Optimizeis never set for Test/Release, andMyGame.BuilderlosesAllowUnsafeBlocksand fails to compile.
DotRush also cannot be told a configuration from outside — its selection lives in its
own workspace state — so this extension owns the build rather than wrapping
dotrush: Build. The startup project is synced with DotRush in both directions
(dotnetSolution.syncDotRush), so its test explorer, launchSettings.json lookup and
${command:dotrush.activeProjectPath} all agree with what the status bar says.
What a build does
dotnetSolution.buildScope decides (default solution):
| Scope | Command | Notes |
|---|---|---|
solution |
dotnet build MyGame.sln -c Test -p:Platform=x64 |
Like Visual Studio's Build Solution. MSBuild maps every project through the .sln: MyGame.* build as Test|x64, MoonWorks as Debug|Any CPU, and the Editor → Builder ProjectDependencies entry is honoured, so the Builder exists before the Editor's post-build step needs it. |
project |
dotnet build MyGame.Editor.csproj -c Test -p:Platform=x64 |
Only the startup project and its ProjectReferences. Faster, but solution-only dependencies are ignored. |
Rebuild adds --no-incremental; Clean runs dotnet clean. All three are tasks of type
dotnet-solution, so they show up under Run Task and can be used as preLaunchTask.
What a launch does
program comes from MSBuild, not from guessing: the extension evaluates the startup
project with the mapped configuration and platform (dotnet msbuild -getProperty:TargetPath …),
which is the only way to get it right here — OutDir comes from Directory.Build.props
and AppendTargetFrameworkToOutputPath is off. The result is cached until a project or
solution file changes.
The apphost .exe is launched when the project produces one, since vsdbg wants an
executable; otherwise it runs dotnet <TargetPath>. Working directory is TargetDir
unless dotnetSolution.launch.cwd says otherwise. DotRush's debug configuration provider
still runs after this one and fills in justMyCode, symbol options and the console.
Usage
| Action | How |
|---|---|
| Pick the startup project | Click the project name, or right-click a .csproj → Set as Startup Project (.NET Solution) |
| Pick the configuration | Click Debug | x64. Entries the solution does not build the project under are marked with $(warning) |
| Build / Rebuild / Clean | .NET Solution: Build etc., or the dotnet-solution tasks |
| Debug | The $(debug-alt) button, .NET Solution: Debug Startup Project, or F5 with the launch.json entry below |
| Run without debugging | .NET Solution: Run Startup Project (without debugging) |
Several .sln files |
.NET Solution: Select Solution, or dotnetSolution.solution |
F5
The first time it sees a solution the extension offers to write a launch.json entry
(.NET Solution: Create launch.json and tasks.json entries does it later):
{
"name": ".NET Solution: Debug startup project",
"type": "coreclr",
"request": "launch",
"program": "${command:dotnetSolution.activeProgram}",
"cwd": "${command:dotnetSolution.activeTargetDir}",
"preLaunchTask": "dotnet-solution: Build"
}
The same entry is offered dynamically in the Run and Debug dropdown even without a
launch.json. It replaces the DotRush template's ${command:dotrush.activeTargetPath} +
preLaunchTask: "dotrush: Build" pair, which is the one that builds without a platform.
Variables for your own launch.json / tasks.json
${command:…} |
Value |
|---|---|
dotnetSolution.activeProgram |
apphost .exe, or the .dll when there is none |
dotnetSolution.activeTargetPath |
the built assembly |
dotnetSolution.activeTargetDir |
its directory |
dotnetSolution.activeProjectPath, activeProjectName |
the startup project |
dotnetSolution.activeSolutionPath |
the solution |
dotnetSolution.activeConfiguration, activePlatform |
solution configuration, e.g. Test, Any CPU |
dotnetSolution.activeProjectConfiguration, activeProjectPlatform |
what the project gets, e.g. Test, AnyCPU |
Settings
| Setting | Default | |
|---|---|---|
dotnetSolution.solution |
"" |
Solution to use; empty picks the shallowest, then the largest |
dotnetSolution.buildScope |
solution |
See above |
dotnetSolution.targetFramework |
"" |
For TargetFrameworks projects; empty takes the first |
dotnetSolution.launch.args / .env / .cwd / .console |
Passed to the launched application | |
dotnetSolution.debugType |
coreclr |
|
dotnetSolution.syncDotRush |
true |
Push the startup project to DotRush and follow its changes |
dotnetSolution.syncDotRushWorkspaceProperties |
false |
Write Configuration=…;Platform=… into dotrush.roslyn.workspaceProperties so IntelliSense sees the same DefineConstants. Off because DotRush reloads its workspace on every change |
dotnetSolution.additionalBuildArguments |
[] |
Appended to every build |
dotrush.roslyn.dotnetSdkDirectory and dotrush.msbuild.additionalEnvironment are
honoured, so both extensions use the same SDK.
Tips
- DotRush's own
Debug | net10.0item can be hidden: right-click the status bar and untick DotRush. Nothing else depends on it once this extension drives the build. - The status bar goes to a spinner while a build runs; the build output is in the
terminal and the Problems panel (
$msCompile). - The .NET Solution output channel logs every
dotnetinvocation.
Development
npm install
npm run compile
npm run test:unit # parser tests, against D:\Projects\MyGame when present
npm test # launches VS Code on that folder (SOLUTION_TEST_FOLDER overrides)