Skip to content

Add support for workingDirectory in launch profiles (#56128) - #56129

Open
StoneLabs wants to merge 3 commits into
dotnet:mainfrom
StoneLabs:fix-launchsettings-workingdirectory
Open

Add support for workingDirectory in launch profiles (#56128)#56129
StoneLabs wants to merge 3 commits into
dotnet:mainfrom
StoneLabs:fix-launchsettings-workingdirectory

Conversation

@StoneLabs

@StoneLabs StoneLabs commented Sep 4, 2026

Copy link
Copy Markdown

dotnet run --launch-profile <name> ignores workingDirectory.

Visual Studio and Rider both follow workingDirectory, so the same launchSettings.json produces a different working directory depending on the IDE used. (especially annoying when working in nvim / without an ide.

See #56128 for details on the issue.

Fix

workingDirectory already had code for commandName: "Executable" profiles. I simply moved WorkingDirectory and TryParseWorkingDirectory onto the shared LaunchProfile/LaunchProfileParser base types and parsed the value for Project profiles too.

  • The value is resolved relative to the directory containing the launch settings file, matching the existing Executable behavior.

  • An explicit workingDirectory takes precedence over the RunWorkingDirectory MSBuild property, which still works as the fallback. Unlike RunWorkingDirectory, which is per-project, this allows profiles of the same project to launch in different directories. (identical behaviour to Rider and VS)

Tests

Tested locally.

I also added a minimal test to test/dotnet.Tests/ProjectTools/LaunchSettingsParserTests.cs, but I'm not sure if thats correct tbh.


Fixes #56128
Fixes #20885

@StoneLabs
StoneLabs requested review from a team as code owners September 4, 2026 05:34
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
2 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@StoneLabs StoneLabs changed the title Honor workingDirectory in Project launch profiles Add support for workingDirectory in launch profiles (#56128) Sep 4, 2026
@StoneLabs

Copy link
Copy Markdown
Author

@dotnet-policy-service agree

`workingDirectory` was already modeled and resolved for
`commandName: "Executable"` profiles. I simply moved
`WorkingDirectory` and `TryParseWorkingDirectory` onto
the shared `LaunchProfile`/`LaunchProfileParser` base
types and parsed the value for Project profiles too.

The value is resolved relative to the directory
containing the launch settings file, matching the
existing Executable behavior.

An explicit `workingDirectory` takes precedence over
the `RunWorkingDirectory` MSBuild property, which
remains the fallback. Unlike `RunWorkingDirectory`,
which is per-project, this allows profiles of the
same project to launch in different directories.

Details can be found in dotnet#56128.

Fixes dotnet#56128
Fixes dotnet#20885
@StoneLabs
StoneLabs force-pushed the fix-launchsettings-workingdirectory branch from 03357aa to c8552aa Compare September 4, 2026 08:46
Comment thread src/Cli/dotnet/Commands/Run/RunCommand.cs
…rkingdirectory

# Conflicts:
#	src/Cli/dotnet/Commands/Run/RunCommand.cs
#	src/Microsoft.DotNet.ProjectTools/LaunchSettings/ExecutableLaunchProfileParser.cs
#	src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfileParser.cs
#	src/Microsoft.DotNet.ProjectTools/LaunchSettings/ProjectLaunchProfileParser.cs
#	test/dotnet.Tests/ProjectTools/LaunchSettingsParserTests.cs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Project-path resolution and MSBuild expansion handling remain incorrect.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds workingDirectory support for Project launch profiles in managed and Native AOT dotnet run.

Changes:

  • Shares working-directory parsing across launch profile types.
  • Gives profile directories precedence over RunWorkingDirectory.
  • Adds parser and managed-run tests.
File summaries
File Review
test/dotnet.Tests/ProjectTools/LaunchSettingsParserTests.cs Adds parser coverage.
test/dotnet.Tests/CommandTests/Run/RunCommandTests.cs Tests managed-run precedence.
src/Microsoft.DotNet.ProjectTools/LaunchSettings/ProjectLaunchProfileParser.cs Adds Project-profile parsing, but relative-path bases and deferred MSBuild expansion require correction.
src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfileParser.cs Centralizes parsing, but Project paths incorrectly resolve relative to Properties.
src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfile.cs Defines the shared working-directory property.
src/Microsoft.DotNet.ProjectTools/LaunchSettings/ExecutableLaunchProfileParser.cs Uses shared parsing logic.
src/Microsoft.DotNet.ProjectTools/LaunchSettings/ExecutableLaunchProfile.cs Inherits the shared property.
src/Cli/dotnet/Commands/Run/RunCommand.cs Applies profile precedence for managed runs.
src/Cli/dotnet/Commands/Run/AotRunCommand.cs Applies profile directories, but MSBuild detection must include them; AOT regression coverage is also missing.
Review details

Suppressed comments (1)

src/Cli/dotnet/Commands/Run/AotRunCommand.cs:154

  • This new native execution behavior has no AOT-path regression coverage. The existing AotIntegrationTests ProjectProfile already prints and asserts its current directory, so add a relative workingDirectory to that profile and update the assertion to prove the native artifact resolves and uses it; managed RunCommandTests cannot catch divergence in this branch.
            workingDirectory = profileResult.Profile?.WorkingDirectory
                ?? validatedRunProperties?.WorkingDirectory
                ?? currentDirectory;
  • Files reviewed: 9/9 changed files
  • Comments generated: 4
  • Review effort level: Balanced

Comment on lines +152 to +154
workingDirectory = profileResult.Profile?.WorkingDirectory
?? validatedRunProperties?.WorkingDirectory
?? currentDirectory;

try
{
workingDirectory = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(launchSettingsPath)!, expandedValue));
return LaunchProfileParseResult.Failure(Resources.LaunchProfileIsNotAJsonObject);
}

if (!TryParseWorkingDirectory(launchSettingsPath, profile.WorkingDirectory, evaluateExpression, out var workingDirectory, out var error))
ApplicationUrl = !expandApplicationUrl || profile.ApplicationUrl is null
? profile.ApplicationUrl
: ExpandMSBuildProperties(profile.ApplicationUrl, evaluateExpression),
WorkingDirectory = profile.WorkingDirectory,
@StoneLabs

StoneLabs commented Sep 4, 2026

Copy link
Copy Markdown
Author

@jjonescz First time contributor here, so i'd appreciate your help with two quick questions!

First:

Which directory should workingDirectory be relative to? I originally matched the existing "Executable" behavior (= relative to the launchSettings.json file), which is what RunCommandTests.cs on main asserts:

Assert.AreEqual(Path.Combine(launchSettingsDirectory, "working"), model.WorkingDirectory);

Copilot complained about it in its review, though, saying it should be relative to the project root. I assume because VS also resolves relative to the project directory, not the launchSettings.json, for both Project and Executable profile (L303-304 of this file in dotnet/project-system). Rider also does relative to project root.

What should I do here?

Second: should $(…) expansion be part of this PR?

launchSettings.json commandName main today this PR as pushed Copilot's review asks for
Executable workingDirectory honored relative to settings dir; $() expanded unchanged unchanged
Project workingDirectory ignored entirely workingDirectory honored relative to settings dir; $() not expanded workingDirectory honored relative to project dir; $() expanded

I'm happy to do the expansion here if i should. It needs path resolution to move after expansion, but that's mostly relocating existing code i think. Otherwise I can ignore $(…) values for Project profiles for now, and file a follow-up PR later.

Thanks!

Verifies that an explicit workingDirectory in a Project launch profile
overrides <RunWorkingDirectory> in the project.
@StoneLabs
StoneLabs force-pushed the fix-launchsettings-workingdirectory branch from 8a42f8f to cf789b2 Compare September 4, 2026 15:36
@jjonescz

jjonescz commented Sep 7, 2026

Copy link
Copy Markdown
Member

Which directory should workingDirectory be relative to?

That's an interesting question, especially since it seems to be already inconsistent (IIUC, VS/Rider disagrees with CLI for the Executable profile). Tagging @dotnet/dotnet-cli @baronfel for thoughts.

Second: should $(…) expansion be part of this PR?

I think either should be fine. If you choose to do it in a follow up, consider filing a tracking issue for it though.

Btw, do you know whether VS and Rider support $() expansion in workingDirectory for Project launch profiles?

@StoneLabs

Copy link
Copy Markdown
Author

Btw, do you know whether VS and Rider support $() expansion in workingDirectory for Project launch profiles?

I quickly checked, and at least Rider does support it without issues. I don't have access to VS right now, so i can't test it.

image psd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants