From 7c2b3dc0b548aa93b27209717eb425d46eb99b14 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Mon, 14 Jul 2025 14:38:52 +0200 Subject: [PATCH 1/5] Disallow using `--launch-profile` with `dotnet run -` --- src/Cli/dotnet/Commands/Run/RunCommand.cs | 8 +++++++- test/dotnet.Tests/CommandTests/Run/RunFileTests.cs | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Cli/dotnet/Commands/Run/RunCommand.cs b/src/Cli/dotnet/Commands/Run/RunCommand.cs index ec1cde6e6a46..95a7051a4d66 100644 --- a/src/Cli/dotnet/Commands/Run/RunCommand.cs +++ b/src/Cli/dotnet/Commands/Run/RunCommand.cs @@ -552,6 +552,7 @@ public static RunCommand FromParseResult(ParseResult parseResult) string? projectFilePath = DiscoverProjectFilePath(projectOption, readCodeFromStdin, ref args, out string? entryPointFilePath); bool noBuild = parseResult.HasOption(RunCommandParser.NoBuildOption); + string launchProfile = parseResult.GetValue(RunCommandParser.LaunchProfileOption) ?? string.Empty; if (readCodeFromStdin && entryPointFilePath != null) { @@ -562,6 +563,11 @@ public static RunCommand FromParseResult(ParseResult parseResult) throw new GracefulException(CliCommandStrings.InvalidOptionForStdin, RunCommandParser.NoBuildOption.Name); } + if (!string.IsNullOrWhiteSpace(launchProfile)) + { + throw new GracefulException(CliCommandStrings.InvalidOptionForStdin, RunCommandParser.LaunchProfileOption.Name); + } + // If '-' is specified as the input file, read all text from stdin into a temporary file and use that as the entry point. // We create a new directory for each file so other files are not included in the compilation. // We fail if the file already exists to avoid reusing the same file for multiple stdin runs (in case the random name is duplicate). @@ -584,7 +590,7 @@ public static RunCommand FromParseResult(ParseResult parseResult) noBuild: noBuild, projectFileFullPath: projectFilePath, entryPointFileFullPath: entryPointFilePath, - launchProfile: parseResult.GetValue(RunCommandParser.LaunchProfileOption) ?? string.Empty, + launchProfile: launchProfile, noLaunchProfile: parseResult.HasOption(RunCommandParser.NoLaunchProfileOption), noLaunchProfileArguments: parseResult.HasOption(RunCommandParser.NoLaunchProfileArgumentsOption), noRestore: parseResult.HasOption(RunCommandParser.NoRestoreOption) || parseResult.HasOption(RunCommandParser.NoBuildOption), diff --git a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs index 98b62c75dd06..790918d13773 100644 --- a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs +++ b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs @@ -365,6 +365,15 @@ public void ReadFromStdin_NoBuild() .And.HaveStdErrContaining(string.Format(CliCommandStrings.InvalidOptionForStdin, RunCommandParser.NoBuildOption.Name)); } + [Fact] + public void ReadFromStdin_LaunchProfile() + { + new DotnetCommand(Log, "run", "-", "--launch-profile=test") + .Execute() + .Should().Fail() + .And.HaveStdErrContaining(string.Format(CliCommandStrings.InvalidOptionForStdin, RunCommandParser.LaunchProfileOption.Name)); + } + /// /// dotnet run -- - should NOT read the C# file from stdin, /// the hyphen should be considred an app argument instead since it's after --. From 95dd2dd711f1c5ed8018a7be01c4778febd5c569 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Mon, 14 Jul 2025 15:24:24 +0200 Subject: [PATCH 2/5] Add support for flat launch settings --- .../dotnet-watch/Browser/BrowserConnector.cs | 5 +- .../Process/LaunchSettingsProfile.cs | 18 +++- .../dotnet/Commands/CliCommandStrings.resx | 10 ++- .../dotnet/Commands/Run/CommonRunHelpers.cs | 6 ++ .../LaunchSettings/LaunchSettingsManager.cs | 5 +- src/Cli/dotnet/Commands/Run/RunCommand.cs | 43 +++++---- .../Test/SolutionAndProjectUtility.cs | 14 +-- .../Commands/xlf/CliCommandStrings.cs.xlf | 20 ++--- .../Commands/xlf/CliCommandStrings.de.xlf | 20 ++--- .../Commands/xlf/CliCommandStrings.es.xlf | 20 ++--- .../Commands/xlf/CliCommandStrings.fr.xlf | 20 ++--- .../Commands/xlf/CliCommandStrings.it.xlf | 20 ++--- .../Commands/xlf/CliCommandStrings.ja.xlf | 20 ++--- .../Commands/xlf/CliCommandStrings.ko.xlf | 20 ++--- .../Commands/xlf/CliCommandStrings.pl.xlf | 20 ++--- .../Commands/xlf/CliCommandStrings.pt-BR.xlf | 20 ++--- .../Commands/xlf/CliCommandStrings.ru.xlf | 20 ++--- .../Commands/xlf/CliCommandStrings.tr.xlf | 20 ++--- .../xlf/CliCommandStrings.zh-Hans.xlf | 20 ++--- .../xlf/CliCommandStrings.zh-Hant.xlf | 20 ++--- .../Process/LaunchSettingsProfileTest.cs | 12 +-- .../Run/GivenDotnetRunBuildsCsProj.cs | 18 ++-- .../Run/GivenDotnetRunBuildsVbProj.cs | 18 ++-- .../CommandTests/Run/RunFileTests.cs | 89 ++++++++++++++++++- .../Test/GivenDotnetTestBuildsAndRunsTests.cs | 12 ++- ...apshotTests.VerifyCompletions.verified.ps1 | 2 +- ...apshotTests.VerifyCompletions.verified.zsh | 2 +- 27 files changed, 309 insertions(+), 205 deletions(-) diff --git a/src/BuiltInTools/dotnet-watch/Browser/BrowserConnector.cs b/src/BuiltInTools/dotnet-watch/Browser/BrowserConnector.cs index 9d3c61515bf8..2cd69c10f85b 100644 --- a/src/BuiltInTools/dotnet-watch/Browser/BrowserConnector.cs +++ b/src/BuiltInTools/dotnet-watch/Browser/BrowserConnector.cs @@ -299,11 +299,8 @@ public bool IsServerSupported(ProjectGraphNode projectNode, HotReloadAppModel ap private LaunchSettingsProfile GetLaunchProfile(ProjectOptions projectOptions) { - var projectDirectory = Path.GetDirectoryName(projectOptions.ProjectPath); - Debug.Assert(projectDirectory != null); - return (projectOptions.NoLaunchProfile == true - ? null : LaunchSettingsProfile.ReadLaunchProfile(projectDirectory, projectOptions.LaunchProfileName, context.Reporter)) ?? new(); + ? null : LaunchSettingsProfile.ReadLaunchProfile(projectOptions.ProjectPath, projectOptions.LaunchProfileName, context.Reporter)) ?? new(); } } } diff --git a/src/BuiltInTools/dotnet-watch/Process/LaunchSettingsProfile.cs b/src/BuiltInTools/dotnet-watch/Process/LaunchSettingsProfile.cs index 75994a9bff86..86697bcc8053 100644 --- a/src/BuiltInTools/dotnet-watch/Process/LaunchSettingsProfile.cs +++ b/src/BuiltInTools/dotnet-watch/Process/LaunchSettingsProfile.cs @@ -2,8 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Text.Json; using System.Text.Json.Serialization; +using Microsoft.DotNet.Cli.Commands.Run; namespace Microsoft.DotNet.Watch { @@ -22,12 +24,20 @@ internal sealed class LaunchSettingsProfile public bool LaunchBrowser { get; init; } public string? LaunchUrl { get; init; } - internal static LaunchSettingsProfile? ReadLaunchProfile(string projectDirectory, string? launchProfileName, IReporter reporter) + internal static LaunchSettingsProfile? ReadLaunchProfile(string projectPath, string? launchProfileName, IReporter reporter) { - var launchSettingsPath = Path.Combine(projectDirectory, "Properties", "launchSettings.json"); + var projectDirectory = Path.GetDirectoryName(projectPath); + Debug.Assert(projectDirectory != null); + + var launchSettingsPath = CommonRunHelpers.GetPropertiesLaunchSettingsPath(projectDirectory, "Properties"); if (!File.Exists(launchSettingsPath)) { - return null; + var projectNameWithoutExtension = Path.GetFileNameWithoutExtension(projectPath); + launchSettingsPath = CommonRunHelpers.GetFlatLaunchSettingsPath(projectDirectory, projectNameWithoutExtension); + if (!File.Exists(launchSettingsPath)) + { + return null; + } } LaunchSettingsJson? launchSettings; @@ -39,7 +49,7 @@ internal sealed class LaunchSettingsProfile } catch (Exception ex) { - reporter.Verbose($"Error reading launchSettings.json: {ex}."); + reporter.Verbose($"Error reading '{launchSettingsPath}': {ex}."); return null; } diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx index 75c76f009030..3c3db3cf553f 100644 --- a/src/Cli/dotnet/Commands/CliCommandStrings.resx +++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx @@ -663,7 +663,8 @@ dotnet.config is a name don't translate. Do not use arguments specified in launch profile to run the application. - Do not attempt to use launchSettings.json to configure the application. + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -731,8 +732,8 @@ dotnet.config is a name don't translate. Description - An error was encountered when reading launchSettings.json. -{0} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -1672,7 +1673,8 @@ The default is to publish a framework-dependent application. {1} - The specified launch profile '{0}' could not be located. + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} Specify which project file to use because {0} contains more than one project file. diff --git a/src/Cli/dotnet/Commands/Run/CommonRunHelpers.cs b/src/Cli/dotnet/Commands/Run/CommonRunHelpers.cs index 42319ae30e39..c9b0880a383d 100644 --- a/src/Cli/dotnet/Commands/Run/CommonRunHelpers.cs +++ b/src/Cli/dotnet/Commands/Run/CommonRunHelpers.cs @@ -36,4 +36,10 @@ public static Dictionary GetGlobalPropertiesFromArgs(string[] ar } return globalProperties; } + + public static string GetPropertiesLaunchSettingsPath(string directoryPath, string propertiesDirectoryName) + => Path.Combine(directoryPath, propertiesDirectoryName, "launchSettings.json"); + + public static string GetFlatLaunchSettingsPath(string directoryPath, string projectNameWithoutExtension) + => Path.Join(directoryPath, $"{projectNameWithoutExtension}.run.json"); } diff --git a/src/Cli/dotnet/Commands/Run/LaunchSettings/LaunchSettingsManager.cs b/src/Cli/dotnet/Commands/Run/LaunchSettings/LaunchSettingsManager.cs index c46fee8aaa15..a1776027476d 100644 --- a/src/Cli/dotnet/Commands/Run/LaunchSettings/LaunchSettingsManager.cs +++ b/src/Cli/dotnet/Commands/Run/LaunchSettings/LaunchSettingsManager.cs @@ -22,8 +22,9 @@ static LaunchSettingsManager() }; } - public static LaunchSettingsApplyResult TryApplyLaunchSettings(string launchSettingsJsonContents, string? profileName = null) + public static LaunchSettingsApplyResult TryApplyLaunchSettings(string launchSettingsPath, string? profileName = null) { + var launchSettingsJsonContents = File.ReadAllText(launchSettingsPath); try { var jsonDocumentOptions = new JsonDocumentOptions @@ -115,7 +116,7 @@ public static LaunchSettingsApplyResult TryApplyLaunchSettings(string launchSett } catch (JsonException ex) { - return new LaunchSettingsApplyResult(false, string.Format(CliCommandStrings.DeserializationExceptionMessage, ex.Message)); + return new LaunchSettingsApplyResult(false, string.Format(CliCommandStrings.DeserializationExceptionMessage, launchSettingsPath, ex.Message)); } } diff --git a/src/Cli/dotnet/Commands/Run/RunCommand.cs b/src/Cli/dotnet/Commands/Run/RunCommand.cs index 95a7051a4d66..f265d28a57c3 100644 --- a/src/Cli/dotnet/Commands/Run/RunCommand.cs +++ b/src/Cli/dotnet/Commands/Run/RunCommand.cs @@ -200,13 +200,9 @@ internal bool TryGetLaunchProfileSettingsIfNeeded(out ProjectLaunchSettingsModel return true; } - var launchSettingsPath = ReadCodeFromStdin ? null : TryFindLaunchSettings(ProjectFileFullPath ?? EntryPointFileFullPath!); - if (!File.Exists(launchSettingsPath)) + var launchSettingsPath = ReadCodeFromStdin ? null : TryFindLaunchSettings(projectOrEntryPointFilePath: ProjectFileFullPath ?? EntryPointFileFullPath!, launchProfile: LaunchProfile); + if (launchSettingsPath is null) { - if (!string.IsNullOrEmpty(LaunchProfile)) - { - Reporter.Error.WriteLine(string.Format(CliCommandStrings.RunCommandExceptionCouldNotLocateALaunchSettingsFile, launchSettingsPath).Bold().Red()); - } return true; } @@ -219,8 +215,7 @@ internal bool TryGetLaunchProfileSettingsIfNeeded(out ProjectLaunchSettingsModel try { - var launchSettingsFileContents = File.ReadAllText(launchSettingsPath); - var applyResult = LaunchSettingsManager.TryApplyLaunchSettings(launchSettingsFileContents, LaunchProfile); + var applyResult = LaunchSettingsManager.TryApplyLaunchSettings(launchSettingsPath, LaunchProfile); if (!applyResult.Success) { Reporter.Error.WriteLine(string.Format(CliCommandStrings.RunCommandExceptionCouldNotApplyLaunchSettings, profileName, applyResult.FailureReason).Bold().Red()); @@ -239,13 +234,9 @@ internal bool TryGetLaunchProfileSettingsIfNeeded(out ProjectLaunchSettingsModel return true; - static string? TryFindLaunchSettings(string projectOrEntryPointFilePath) + static string? TryFindLaunchSettings(string projectOrEntryPointFilePath, string? launchProfile) { - var buildPathContainer = File.Exists(projectOrEntryPointFilePath) ? Path.GetDirectoryName(projectOrEntryPointFilePath) : projectOrEntryPointFilePath; - if (buildPathContainer is null) - { - return null; - } + var buildPathContainer = File.Exists(projectOrEntryPointFilePath) ? Path.GetDirectoryName(projectOrEntryPointFilePath)! : projectOrEntryPointFilePath; string propsDirectory; @@ -261,8 +252,28 @@ internal bool TryGetLaunchProfileSettingsIfNeeded(out ProjectLaunchSettingsModel propsDirectory = "Properties"; } - var launchSettingsPath = Path.Combine(buildPathContainer, propsDirectory, "launchSettings.json"); - return launchSettingsPath; + var launchSettingsPath = CommonRunHelpers.GetPropertiesLaunchSettingsPath(buildPathContainer, propsDirectory); + if (File.Exists(launchSettingsPath)) + { + return launchSettingsPath; + } + + string appName = Path.GetFileNameWithoutExtension(projectOrEntryPointFilePath); + string runJsonPath = CommonRunHelpers.GetFlatLaunchSettingsPath(buildPathContainer, appName); + if (File.Exists(runJsonPath)) + { + return runJsonPath; + } + + if (!string.IsNullOrEmpty(launchProfile)) + { + Reporter.Error.WriteLine(string.Format(CliCommandStrings.RunCommandExceptionCouldNotLocateALaunchSettingsFile, launchProfile, $""" + {launchSettingsPath} + {runJsonPath} + """).Red()); + } + + return null; } } diff --git a/src/Cli/dotnet/Commands/Test/SolutionAndProjectUtility.cs b/src/Cli/dotnet/Commands/Test/SolutionAndProjectUtility.cs index 53fe677a4a44..37ee1dfab4c7 100644 --- a/src/Cli/dotnet/Commands/Test/SolutionAndProjectUtility.cs +++ b/src/Cli/dotnet/Commands/Test/SolutionAndProjectUtility.cs @@ -248,7 +248,7 @@ public static IEnumerable - Do not attempt to use launchSettings.json to configure the application. - Ke konfiguraci aplikace nepoužívejte launchSettings.json. - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + Ke konfiguraci aplikace nepoužívejte launchSettings.json. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - Při načítání launchSettings.json došlo k chybě. -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ Ve výchozím nastavení je publikována aplikace závislá na architektuře. - The specified launch profile '{0}' could not be located. - Zadaný profil spuštění {0} se nenašel. + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf index f70cb9600a52..a42f4861cd03 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - Versuchen Sie nicht, "launchSettings.json" zum Konfigurieren der Anwendung zu verwenden. - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + Versuchen Sie nicht, "launchSettings.json" zum Konfigurieren der Anwendung zu verwenden. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - Beim Lesen von "launchSettings.json" ist ein Fehler aufgetreten. -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ Standardmäßig wird eine Framework-abhängige Anwendung veröffentlicht. - The specified launch profile '{0}' could not be located. - Das angegebene Startprofil "{0}" wurde nicht gefunden. + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf index e349ccd9aae5..b8738ba52363 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - No intente usar launchSettings.json para configurar la aplicación. - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + No intente usar launchSettings.json para configurar la aplicación. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - Se produjo un error al leer launchSettings.json. -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ El valor predeterminado es publicar una aplicación dependiente del marco. - The specified launch profile '{0}' could not be located. - No se ha podido encontrar el perfil de inicio especificado "{0}". + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf index 9243b52795f5..f27857dff81c 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - N'essayez pas d'utiliser launchSettings.json pour configurer l'application. - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + N'essayez pas d'utiliser launchSettings.json pour configurer l'application. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - Une erreur s'est produite durant la lecture de launchSettings.json. -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ La valeur par défaut est de publier une application dépendante du framework. - The specified launch profile '{0}' could not be located. - Le profil de lancement spécifié '{0}' n'a pas pu être localisé. + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf index a383e84c2284..5f52927bd266 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - Non prova a usare launchSettings.json per configurare l'applicazione. - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + Non prova a usare launchSettings.json per configurare l'applicazione. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - È stato rilevato un errore durante la lettura di launchSettings.json. -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ Per impostazione predefinita, viene generato un pacchetto dipendente dal framewo - The specified launch profile '{0}' could not be located. - Il profilo di avvio specificato '{0}' non è stato trovato. + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf index 12b1a2d0d6e0..b6307d9c7c79 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - launchSettings.json の使用によるアプリケーションの構成は行わないでください。 - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + launchSettings.json の使用によるアプリケーションの構成は行わないでください。 + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - launchSettings.json を読み取るときにエラーが発生しました。 -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ The default is to publish a framework-dependent application. - The specified launch profile '{0}' could not be located. - 指定された起動プロファイル '{0}' が見つかりませんでした。 + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf index 6f1e0be285b6..8ea791140e6a 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - launchSettings.json을 사용하여 애플리케이션을 구성하지 마세요. - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + launchSettings.json을 사용하여 애플리케이션을 구성하지 마세요. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - launchSettings.json을 읽는 동안 오류가 발생했습니다. -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ The default is to publish a framework-dependent application. - The specified launch profile '{0}' could not be located. - 지정한 '{0}' 시작 프로필을 찾을 수 없습니다. + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf index 950656ce22f2..00226516cf5f 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - Nie próbuj konfigurować aplikacji za pomocą pliku launchSettings.json. - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + Nie próbuj konfigurować aplikacji za pomocą pliku launchSettings.json. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - Wystąpił błąd podczas odczytywania pliku launchSettings.json. -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ Domyślnie publikowana jest aplikacja zależna od struktury. - The specified launch profile '{0}' could not be located. - Nie można odnaleźć określonego profilu uruchamiania „{0}”. + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf index d8bb4763fa06..2db5e00f0594 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - Não tente usar o launchSettings.json para configurar o aplicativo. - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + Não tente usar o launchSettings.json para configurar o aplicativo. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - Um erro foi encontrado durante a leitura do launchSettings.json. -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ O padrão é publicar uma aplicação dependente de framework. - The specified launch profile '{0}' could not be located. - O perfil de inicialização especificado '{0}' não pôde ser localizado. + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf index b605c45c2d9e..903d0ab8c2e7 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - Не используйте launchSettings.json для настройки приложения. - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + Не используйте launchSettings.json для настройки приложения. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - При чтении launchSettings.json обнаружена ошибка. -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ The default is to publish a framework-dependent application. - The specified launch profile '{0}' could not be located. - Не удалось найти указанный профиль запуска "{0}". + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf index 7eb51cb17ed3..36854db4eb7a 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - Uygulamayı yapılandırmak için launchSettings.json kullanmayı denemeyin. - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + Uygulamayı yapılandırmak için launchSettings.json kullanmayı denemeyin. + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - launchSettings.json okunurken bir hatayla karşılaşıldı. -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ Varsayılan durum, çerçeveye bağımlı bir uygulama yayımlamaktır. - The specified launch profile '{0}' could not be located. - Belirtilen başlatma profili '{0}' bulunamadı. + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf index 3d1c446d846d..35a63c9ae963 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - 请勿尝试使用 launchSettings.json 配置应用程序。 - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + 请勿尝试使用 launchSettings.json 配置应用程序。 + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - 读取 launchSettings.json 时发生错误。 -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ The default is to publish a framework-dependent application. - The specified launch profile '{0}' could not be located. - 找不到指定的启动配置文件“{0}”。 + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf index af3ea934d94f..26596c5f808f 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf @@ -906,9 +906,9 @@ dotnet.config is a name don't translate. - Do not attempt to use launchSettings.json to configure the application. - 請勿嘗試使用 launchSettings.json 設定該應用程式。 - + Do not attempt to use launchSettings.json or [app].run.json to configure the application. + 請勿嘗試使用 launchSettings.json 設定該應用程式。 + {Locked="launchSettings.json"}{Locked=".run.json"} The path to the project file to run (defaults to the current directory if there is only one project). @@ -1031,11 +1031,9 @@ dotnet.config is a name don't translate. - An error was encountered when reading launchSettings.json. -{0} - 讀取 launchSettings.json 時發生錯誤。 -{0} - + An error was encountered when reading '{0}': {1} + An error was encountered when reading '{0}': {1} + {0} is file path. {1} is exception message. Show detail result of the query. @@ -2530,8 +2528,10 @@ The default is to publish a framework-dependent application. - The specified launch profile '{0}' could not be located. - 找不到指定的啟動設定檔 '{0}'。 + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} + Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: +{1} diff --git a/test/dotnet-watch.Tests/Process/LaunchSettingsProfileTest.cs b/test/dotnet-watch.Tests/Process/LaunchSettingsProfileTest.cs index 44b57449f1c3..937cf6ddcf34 100644 --- a/test/dotnet-watch.Tests/Process/LaunchSettingsProfileTest.cs +++ b/test/dotnet-watch.Tests/Process/LaunchSettingsProfileTest.cs @@ -46,17 +46,17 @@ public void LoadsLaunchProfiles() } """); - var projectDirectory = Path.Combine(project.TestRoot, "Project1"); + var projectPath = Path.Combine(project.TestRoot, "Project1", "Project1.csproj"); - var expected = LaunchSettingsProfile.ReadLaunchProfile(projectDirectory, "http", _reporter); + var expected = LaunchSettingsProfile.ReadLaunchProfile(projectPath, launchProfileName: "http", _reporter); Assert.NotNull(expected); Assert.Equal("http://localhost:5000", expected.ApplicationUrl); - expected = LaunchSettingsProfile.ReadLaunchProfile(projectDirectory, "https", _reporter); + expected = LaunchSettingsProfile.ReadLaunchProfile(projectPath, "https", _reporter); Assert.NotNull(expected); Assert.Equal("https://localhost:5001", expected.ApplicationUrl); - expected = LaunchSettingsProfile.ReadLaunchProfile(projectDirectory, "notfound", _reporter); + expected = LaunchSettingsProfile.ReadLaunchProfile(projectPath, "notfound", _reporter); Assert.NotNull(expected); } @@ -79,9 +79,9 @@ public void DefaultLaunchProfileWithoutProjectCommand() } """); - var projectDirectory = Path.Combine(project.TestRoot, "Project1"); + var projectPath = Path.Combine(project.Path, "Project1", "Project1.csproj"); - var expected = LaunchSettingsProfile.ReadLaunchProfile(projectDirectory, launchProfileName: null, _reporter); + var expected = LaunchSettingsProfile.ReadLaunchProfile(projectPath, launchProfileName: null, _reporter); Assert.Null(expected); } diff --git a/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunBuildsCsProj.cs b/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunBuildsCsProj.cs index 61c557fde2b3..06b7449494ac 100644 --- a/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunBuildsCsProj.cs +++ b/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunBuildsCsProj.cs @@ -375,19 +375,13 @@ public void ItGivesAnErrorWhenAttemptingToUseALaunchProfileThatDoesNotExistWhenT .WithWorkingDirectory(testProjectDirectory) .Execute("--launch-profile", "test"); - string[] expectedErrorWords = CliCommandStrings.RunCommandExceptionCouldNotLocateALaunchSettingsFile - .Replace("\'{0}\'", "") - .Split(" ") - .Where(word => !string.IsNullOrEmpty(word)) - .ToArray(); - runResult - .Should() - .Pass() - .And - .HaveStdOutContaining("Hello World!"); - - expectedErrorWords.ForEach(word => runResult.Should().HaveStdErrContaining(word)); + .Should().Pass() + .And.HaveStdOutContaining("Hello World!") + .And.HaveStdErrContaining(string.Format(CliCommandStrings.RunCommandExceptionCouldNotLocateALaunchSettingsFile, "test", $""" + {Path.Join(testInstance.Path, "Properties", "launchSettings.json")} + {Path.Join(testInstance.Path, "MSBuildTestApp.run.json")} + """)); } [Fact] diff --git a/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunBuildsVbProj.cs b/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunBuildsVbProj.cs index 68c3a1ae210f..751e606b730e 100644 --- a/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunBuildsVbProj.cs +++ b/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunBuildsVbProj.cs @@ -25,19 +25,13 @@ public void ItGivesAnErrorWhenAttemptingToUseALaunchProfileThatDoesNotExistWhenT .WithWorkingDirectory(testProjectDirectory) .Execute("--launch-profile", "test"); - string[] expectedErrorWords = CliCommandStrings.RunCommandExceptionCouldNotLocateALaunchSettingsFile - .Replace("\'{0}\'", "") - .Split(" ") - .Where(word => !string.IsNullOrEmpty(word)) - .ToArray(); - runResult - .Should() - .Pass() - .And - .HaveStdOutContaining("Hello World!"); - - expectedErrorWords.ForEach(word => runResult.Should().HaveStdErrContaining(word)); + .Should().Pass() + .And.HaveStdOutContaining("Hello World!") + .And.HaveStdErrContaining(string.Format(CliCommandStrings.RunCommandExceptionCouldNotLocateALaunchSettingsFile, "test", $""" + {Path.Join(testInstance.Path, "My Project", "launchSettings.json")} + {Path.Join(testInstance.Path, "VBTestApp.run.json")} + """)); } [Fact] diff --git a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs index 790918d13773..1f9ce02cbe6c 100644 --- a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs +++ b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs @@ -1417,16 +1417,19 @@ public void ArtifactsDirectory_Permissions() .Should().Be(actualMode, artifactsDir); } - [Fact] - public void LaunchProfile() + [Theory] + [InlineData("Properties/launchSettings.json")] + [InlineData("Program.run.json")] + public void LaunchProfile(string relativePath) { var testInstance = _testAssetsManager.CreateTestDirectory(); File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), s_program + """ Console.WriteLine($"Message: '{Environment.GetEnvironmentVariable("Message")}'"); """); - Directory.CreateDirectory(Path.Join(testInstance.Path, "Properties")); - File.WriteAllText(Path.Join(testInstance.Path, "Properties", "launchSettings.json"), s_launchSettings); + var fullPath = Path.Join(testInstance.Path, relativePath); + Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!); + File.WriteAllText(fullPath, s_launchSettings); new DotnetCommand(Log, "run", "--no-launch-profile", "Program.cs") .WithWorkingDirectory(testInstance.Path) @@ -1456,6 +1459,84 @@ Hello from Program """); } + /// + /// Properties/launchSettings.json takes precedence over Program.run.json. + /// + [Fact] + public void LaunchProfile_Precedence() + { + var testInstance = _testAssetsManager.CreateTestDirectory(); + File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), s_program + """ + + Console.WriteLine($"Message: '{Environment.GetEnvironmentVariable("Message")}'"); + """); + Directory.CreateDirectory(Path.Join(testInstance.Path, "Properties")); + File.WriteAllText(Path.Join(testInstance.Path, "Properties", "launchSettings.json"), s_launchSettings.Replace("TestProfileMessage", "PropertiesLaunchSettingsJson")); + File.WriteAllText(Path.Join(testInstance.Path, "Program.run.json"), s_launchSettings.Replace("TestProfileMessage", "ProgramRunJson")); + + new DotnetCommand(Log, "run", "--no-launch-profile", "Program.cs") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should().Pass() + .And.HaveStdOut(""" + Hello from Program + Message: '' + """); + + new DotnetCommand(Log, "run", "Program.cs") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should().Pass() + .And.HaveStdOutContaining(""" + Hello from Program + Message: 'PropertiesLaunchSettingsJson1' + """); + + new DotnetCommand(Log, "run", "-lp", "TestProfile2", "Program.cs") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should().Pass() + .And.HaveStdOutContaining(""" + Hello from Program + Message: 'PropertiesLaunchSettingsJson2' + """); + } + + /// + /// Each file-based app in a folder can have separate launch profile. + /// + [Fact] + public void LaunchProfile_Multiple() + { + var testInstance = _testAssetsManager.CreateTestDirectory(); + var source = s_program + """ + + Console.WriteLine($"Message: '{Environment.GetEnvironmentVariable("Message")}'"); + """; + File.WriteAllText(Path.Join(testInstance.Path, "First.cs"), source); + File.WriteAllText(Path.Join(testInstance.Path, "First.run.json"), s_launchSettings.Replace("TestProfileMessage", "First")); + File.WriteAllText(Path.Join(testInstance.Path, "Second.cs"), source); + File.WriteAllText(Path.Join(testInstance.Path, "Second.run.json"), s_launchSettings.Replace("TestProfileMessage", "Second")); + + new DotnetCommand(Log, "run", "First.cs") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should().Pass() + .And.HaveStdOut(""" + Hello from First + Message: 'First1' + """); + + new DotnetCommand(Log, "run", "Second.cs") + .WithWorkingDirectory(testInstance.Path) + .Execute() + .Should().Pass() + .And.HaveStdOut(""" + Hello from Second + Message: 'Second1' + """); + } + [Fact] public void Define_01() { diff --git a/test/dotnet.Tests/CommandTests/Test/GivenDotnetTestBuildsAndRunsTests.cs b/test/dotnet.Tests/CommandTests/Test/GivenDotnetTestBuildsAndRunsTests.cs index 0387b25cf9a9..88f6626a9025 100644 --- a/test/dotnet.Tests/CommandTests/Test/GivenDotnetTestBuildsAndRunsTests.cs +++ b/test/dotnet.Tests/CommandTests/Test/GivenDotnetTestBuildsAndRunsTests.cs @@ -118,14 +118,18 @@ public void RunTestProjectWithTests_ShouldReturnExitCodeSuccess(string configura result.ExitCode.Should().Be(ExitCodes.Success); } - [InlineData(TestingConstants.Debug)] - [InlineData(TestingConstants.Release)] - [Theory] - public void RunTestProjectWithTestsAndLaunchSettings_ShouldReturnExitCodeSuccess(string configuration) + [Theory, CombinatorialData] + public void RunTestProjectWithTestsAndLaunchSettings_ShouldReturnExitCodeSuccess( + [CombinatorialValues(TestingConstants.Debug, TestingConstants.Release)] string configuration, bool runJson) { TestAsset testInstance = _testAssetsManager.CopyTestAsset("TestProjectWithLaunchSettings", Guid.NewGuid().ToString()) .WithSource(); + if (runJson) + { + File.Move(Path.Join(testInstance.Path, "Properties", "launchSettings.json"), Path.Join(testInstance.Path, "TestProjectWithLaunchSettings.run.json")); + } + CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false) .WithWorkingDirectory(testInstance.Path) .Execute(TestingPlatformOptions.ConfigurationOption.Name, configuration); diff --git a/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 b/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 index 15c062affb5b..14c3b0fe4749 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 +++ b/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 @@ -825,7 +825,7 @@ Register-ArgumentCompleter -Native -CommandName 'testhost' -ScriptBlock { [CompletionResult]::new('--project', '--project', [CompletionResultType]::ParameterName, "The path to the project file to run (defaults to the current directory if there is only one project).") [CompletionResult]::new('--launch-profile', '--launch-profile', [CompletionResultType]::ParameterName, "The name of the launch profile (if any) to use when launching the application.") [CompletionResult]::new('--launch-profile', '-lp', [CompletionResultType]::ParameterName, "The name of the launch profile (if any) to use when launching the application.") - [CompletionResult]::new('--no-launch-profile', '--no-launch-profile', [CompletionResultType]::ParameterName, "Do not attempt to use launchSettings.json to configure the application.") + [CompletionResult]::new('--no-launch-profile', '--no-launch-profile', [CompletionResultType]::ParameterName, "Do not attempt to use launchSettings.json or [app].run.json to configure the application.") [CompletionResult]::new('--no-build', '--no-build', [CompletionResultType]::ParameterName, "Do not build the project before running. Implies --no-restore.") [CompletionResult]::new('--interactive', '--interactive', [CompletionResultType]::ParameterName, "Allows the command to stop and wait for user input or action (for example to complete authentication).") [CompletionResult]::new('--no-restore', '--no-restore', [CompletionResultType]::ParameterName, "Do not restore the project before building.") diff --git a/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh b/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh index e0a9103421b7..1ec7bbcc3e76 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh +++ b/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh @@ -860,7 +860,7 @@ _testhost() { '--project=[The path to the project file to run (defaults to the current directory if there is only one project).]:PROJECT_PATH: ' \ '--launch-profile=[The name of the launch profile (if any) to use when launching the application.]:LAUNCH_PROFILE: ' \ '-lp=[The name of the launch profile (if any) to use when launching the application.]:LAUNCH_PROFILE: ' \ - '--no-launch-profile[Do not attempt to use launchSettings.json to configure the application.]' \ + '--no-launch-profile[Do not attempt to use launchSettings.json or \[app\].run.json to configure the application.]' \ '--no-build[Do not build the project before running. Implies --no-restore.]' \ '--interactive=[Allows the command to stop and wait for user input or action (for example to complete authentication).]: :((False\:"False" True\:"True" ))' \ '--no-restore[Do not restore the project before building.]' \ From 04be093cdb20537bdf7b7e4c7a6d326ebf6340d9 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 23 Jul 2025 10:24:20 +0200 Subject: [PATCH 3/5] Remove unnecessary check --- src/Cli/dotnet/Commands/Run/RunCommand.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cli/dotnet/Commands/Run/RunCommand.cs b/src/Cli/dotnet/Commands/Run/RunCommand.cs index f265d28a57c3..acf88d1ba875 100644 --- a/src/Cli/dotnet/Commands/Run/RunCommand.cs +++ b/src/Cli/dotnet/Commands/Run/RunCommand.cs @@ -236,7 +236,7 @@ internal bool TryGetLaunchProfileSettingsIfNeeded(out ProjectLaunchSettingsModel static string? TryFindLaunchSettings(string projectOrEntryPointFilePath, string? launchProfile) { - var buildPathContainer = File.Exists(projectOrEntryPointFilePath) ? Path.GetDirectoryName(projectOrEntryPointFilePath)! : projectOrEntryPointFilePath; + var buildPathContainer = Path.GetDirectoryName(projectOrEntryPointFilePath)!; string propsDirectory; From 995f3320a2a8b6d338d144bbbd0b79a71e23600e Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 23 Jul 2025 10:29:42 +0200 Subject: [PATCH 4/5] Re-add bold --- src/Cli/dotnet/Commands/Run/RunCommand.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cli/dotnet/Commands/Run/RunCommand.cs b/src/Cli/dotnet/Commands/Run/RunCommand.cs index acf88d1ba875..777a4c607186 100644 --- a/src/Cli/dotnet/Commands/Run/RunCommand.cs +++ b/src/Cli/dotnet/Commands/Run/RunCommand.cs @@ -270,7 +270,7 @@ internal bool TryGetLaunchProfileSettingsIfNeeded(out ProjectLaunchSettingsModel Reporter.Error.WriteLine(string.Format(CliCommandStrings.RunCommandExceptionCouldNotLocateALaunchSettingsFile, launchProfile, $""" {launchSettingsPath} {runJsonPath} - """).Red()); + """).Bold().Red()); } return null; From b7229a9dd174adb79e91fa88566bf93db6df98e8 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 23 Jul 2025 10:39:34 +0200 Subject: [PATCH 5/5] Warn if app.run.json is not used --- .../Process/LaunchSettingsProfile.cs | 23 +++++++++++++++---- .../dotnet/Commands/CliCommandStrings.resx | 4 ++++ src/Cli/dotnet/Commands/Run/RunCommand.cs | 19 +++++++++++---- .../Test/SolutionAndProjectUtility.cs | 20 ++++++++++++---- .../Commands/xlf/CliCommandStrings.cs.xlf | 5 ++++ .../Commands/xlf/CliCommandStrings.de.xlf | 5 ++++ .../Commands/xlf/CliCommandStrings.es.xlf | 5 ++++ .../Commands/xlf/CliCommandStrings.fr.xlf | 5 ++++ .../Commands/xlf/CliCommandStrings.it.xlf | 5 ++++ .../Commands/xlf/CliCommandStrings.ja.xlf | 5 ++++ .../Commands/xlf/CliCommandStrings.ko.xlf | 5 ++++ .../Commands/xlf/CliCommandStrings.pl.xlf | 5 ++++ .../Commands/xlf/CliCommandStrings.pt-BR.xlf | 5 ++++ .../Commands/xlf/CliCommandStrings.ru.xlf | 5 ++++ .../Commands/xlf/CliCommandStrings.tr.xlf | 5 ++++ .../xlf/CliCommandStrings.zh-Hans.xlf | 5 ++++ .../xlf/CliCommandStrings.zh-Hant.xlf | 5 ++++ .../CommandTests/Run/RunFileTests.cs | 12 ++++++---- 18 files changed, 125 insertions(+), 18 deletions(-) diff --git a/src/BuiltInTools/dotnet-watch/Process/LaunchSettingsProfile.cs b/src/BuiltInTools/dotnet-watch/Process/LaunchSettingsProfile.cs index 86697bcc8053..6aec6dee3a6b 100644 --- a/src/BuiltInTools/dotnet-watch/Process/LaunchSettingsProfile.cs +++ b/src/BuiltInTools/dotnet-watch/Process/LaunchSettingsProfile.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Text.Json; using System.Text.Json.Serialization; +using Microsoft.DotNet.Cli.Commands; using Microsoft.DotNet.Cli.Commands.Run; namespace Microsoft.DotNet.Watch @@ -30,15 +31,27 @@ internal sealed class LaunchSettingsProfile Debug.Assert(projectDirectory != null); var launchSettingsPath = CommonRunHelpers.GetPropertiesLaunchSettingsPath(projectDirectory, "Properties"); - if (!File.Exists(launchSettingsPath)) + bool hasLaunchSettings = File.Exists(launchSettingsPath); + + var projectNameWithoutExtension = Path.GetFileNameWithoutExtension(projectPath); + var runJsonPath = CommonRunHelpers.GetFlatLaunchSettingsPath(projectDirectory, projectNameWithoutExtension); + bool hasRunJson = File.Exists(runJsonPath); + + if (hasLaunchSettings) { - var projectNameWithoutExtension = Path.GetFileNameWithoutExtension(projectPath); - launchSettingsPath = CommonRunHelpers.GetFlatLaunchSettingsPath(projectDirectory, projectNameWithoutExtension); - if (!File.Exists(launchSettingsPath)) + if (hasRunJson) { - return null; + reporter.Warn(string.Format(CliCommandStrings.RunCommandWarningRunJsonNotUsed, runJsonPath, launchSettingsPath)); } } + else if (hasRunJson) + { + launchSettingsPath = runJsonPath; + } + else + { + return null; + } LaunchSettingsJson? launchSettings; try diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx index 3c3db3cf553f..2ef3fea4c689 100644 --- a/src/Cli/dotnet/Commands/CliCommandStrings.resx +++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx @@ -1676,6 +1676,10 @@ The default is to publish a framework-dependent application. Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: {1} + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + Specify which project file to use because {0} contains more than one project file. diff --git a/src/Cli/dotnet/Commands/Run/RunCommand.cs b/src/Cli/dotnet/Commands/Run/RunCommand.cs index 777a4c607186..d2d4e15da644 100644 --- a/src/Cli/dotnet/Commands/Run/RunCommand.cs +++ b/src/Cli/dotnet/Commands/Run/RunCommand.cs @@ -252,15 +252,24 @@ internal bool TryGetLaunchProfileSettingsIfNeeded(out ProjectLaunchSettingsModel propsDirectory = "Properties"; } - var launchSettingsPath = CommonRunHelpers.GetPropertiesLaunchSettingsPath(buildPathContainer, propsDirectory); - if (File.Exists(launchSettingsPath)) + string launchSettingsPath = CommonRunHelpers.GetPropertiesLaunchSettingsPath(buildPathContainer, propsDirectory); + bool hasLaunchSetttings = File.Exists(launchSettingsPath); + + string appName = Path.GetFileNameWithoutExtension(projectOrEntryPointFilePath); + string runJsonPath = CommonRunHelpers.GetFlatLaunchSettingsPath(buildPathContainer, appName); + bool hasRunJson = File.Exists(runJsonPath); + + if (hasLaunchSetttings) { + if (hasRunJson) + { + Reporter.Output.WriteLine(string.Format(CliCommandStrings.RunCommandWarningRunJsonNotUsed, runJsonPath, launchSettingsPath).Yellow()); + } + return launchSettingsPath; } - string appName = Path.GetFileNameWithoutExtension(projectOrEntryPointFilePath); - string runJsonPath = CommonRunHelpers.GetFlatLaunchSettingsPath(buildPathContainer, appName); - if (File.Exists(runJsonPath)) + if (hasRunJson) { return runJsonPath; } diff --git a/src/Cli/dotnet/Commands/Test/SolutionAndProjectUtility.cs b/src/Cli/dotnet/Commands/Test/SolutionAndProjectUtility.cs index 37ee1dfab4c7..bbad54fd096d 100644 --- a/src/Cli/dotnet/Commands/Test/SolutionAndProjectUtility.cs +++ b/src/Cli/dotnet/Commands/Test/SolutionAndProjectUtility.cs @@ -278,14 +278,26 @@ static RunProperties GetRunProperties(ProjectInstance project, ICollection{0} není platný soubor projektu. + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. Konfigurace pro spuštění. Výchozí možností pro většinu projektů je Debug. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf index a42f4861cd03..798c03a3d0b0 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf @@ -2572,6 +2572,11 @@ Ihr Projekt verwendet mehrere Zielframeworks. Geben Sie über "{0}" an, welches "{0}" ist keine gültige Projektdatei. + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. Die Konfiguration für die Ausführung. Der Standardwert für die meisten Projekte ist "Debug". diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf index b8738ba52363..d328d7273538 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf @@ -2572,6 +2572,11 @@ Su proyecto tiene como destino varias plataformas. Especifique la que quiere usa "{0}" no es un archivo de proyecto válido. + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. La configuración para la que se ejecuta. El valor predeterminado para la mayoría de los proyectos es "Debug". diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf index f27857dff81c..b751761c408c 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf @@ -2572,6 +2572,11 @@ Votre projet cible plusieurs frameworks. Spécifiez le framework à exécuter à '{0}' n'est pas un fichier projet valide. + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. Configuration pour laquelle l'exécution est effectuée. La valeur par défaut pour la plupart des projets est 'Debug'. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf index 5f52927bd266..7fd3c654bd38 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf @@ -2572,6 +2572,11 @@ Il progetto è destinato a più framework. Specificare il framework da eseguire '{0}' non è un file di progetto valido. + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. Configurazione da usare per l'esecuzione. L'impostazione predefinita per la maggior parte dei progetti è 'Debug'. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf index b6307d9c7c79..b57de35e1073 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf @@ -2572,6 +2572,11 @@ Your project targets multiple frameworks. Specify which framework to run using ' '{0}' は有効なプロジェクト ファイルではありません。 + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. 実行する対象の構成。大部分のプロジェクトで、既定値は 'Debug' です。 diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf index 8ea791140e6a..6f1ef72d3cf6 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf @@ -2572,6 +2572,11 @@ Your project targets multiple frameworks. Specify which framework to run using ' '{0}'은(는) 유효한 프로젝트 파일이 아닙니다. + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. 실행할 구성입니다. 대부분의 프로젝트에서 기본값은 'Debug'입니다. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf index 00226516cf5f..207e6783ef16 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf @@ -2572,6 +2572,11 @@ Projekt ma wiele platform docelowych. Określ platformę do uruchomienia przy u „{0}” nie jest prawidłowym plikiem projektu. + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. Konfiguracja, którą należy uruchomić. W przypadku większości projektów ustawienie domyślne to „Debugowanie”. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf index 2db5e00f0594..d5037d6b5d2d 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf @@ -2572,6 +2572,11 @@ Ele tem diversas estruturas como destino. Especifique que estrutura executar usa '{0}' não é um arquivo de projeto válido. + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. A configuração para a qual a execução ocorrerá. O padrão para a maioria dos projetos é 'Debug'. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf index 903d0ab8c2e7..58a09ad78a0c 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf @@ -2572,6 +2572,11 @@ Your project targets multiple frameworks. Specify which framework to run using ' "{0}" не является допустимым файлом проекта. + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. Конфигурация для запуска. По умолчанию для большинства проектов используется "Debug". diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf index 36854db4eb7a..0c52273b86b5 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf @@ -2572,6 +2572,11 @@ Projeniz birden fazla Framework'ü hedefliyor. '{0}' kullanarak hangi Framework' '{0}' geçerli bir proje dosyası değil. + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. Çalıştırılacak yapılandırma. Çoğu proje için varsayılan, ‘Hata Ayıklama’ seçeneğidir. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf index 35a63c9ae963..010aafdef192 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf @@ -2572,6 +2572,11 @@ Your project targets multiple frameworks. Specify which framework to run using ' “{0}”不是有效的项目文件。 + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. 要运行的配置。大多数项目的默认值是 "Debug"。 diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf index 26596c5f808f..96556c6dfe64 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf @@ -2572,6 +2572,11 @@ Your project targets multiple frameworks. Specify which framework to run using ' '{0}' 並非有效的專案名稱。 + + Warning: Settings from '{0}' are not used because '{1}' has precedence. + Warning: Settings from '{0}' are not used because '{1}' has precedence. + {0} is an app.run.json file path. {1} is a launchSettings.json file path. + The configuration to run for. The default for most projects is 'Debug'. 要為其執行的組態。大部分的專案預設為「偵錯」。 diff --git a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs index 1f9ce02cbe6c..ed47c625797e 100644 --- a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs +++ b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs @@ -1471,8 +1471,10 @@ public void LaunchProfile_Precedence() Console.WriteLine($"Message: '{Environment.GetEnvironmentVariable("Message")}'"); """); Directory.CreateDirectory(Path.Join(testInstance.Path, "Properties")); - File.WriteAllText(Path.Join(testInstance.Path, "Properties", "launchSettings.json"), s_launchSettings.Replace("TestProfileMessage", "PropertiesLaunchSettingsJson")); - File.WriteAllText(Path.Join(testInstance.Path, "Program.run.json"), s_launchSettings.Replace("TestProfileMessage", "ProgramRunJson")); + string launchSettings = Path.Join(testInstance.Path, "Properties", "launchSettings.json"); + File.WriteAllText(launchSettings, s_launchSettings.Replace("TestProfileMessage", "PropertiesLaunchSettingsJson")); + string runJson = Path.Join(testInstance.Path, "Program.run.json"); + File.WriteAllText(runJson, s_launchSettings.Replace("TestProfileMessage", "ProgramRunJson")); new DotnetCommand(Log, "run", "--no-launch-profile", "Program.cs") .WithWorkingDirectory(testInstance.Path) @@ -1487,7 +1489,8 @@ Hello from Program .WithWorkingDirectory(testInstance.Path) .Execute() .Should().Pass() - .And.HaveStdOutContaining(""" + .And.HaveStdOut($""" + {string.Format(CliCommandStrings.RunCommandWarningRunJsonNotUsed, runJson, launchSettings)} Hello from Program Message: 'PropertiesLaunchSettingsJson1' """); @@ -1496,7 +1499,8 @@ Hello from Program .WithWorkingDirectory(testInstance.Path) .Execute() .Should().Pass() - .And.HaveStdOutContaining(""" + .And.HaveStdOut($""" + {string.Format(CliCommandStrings.RunCommandWarningRunJsonNotUsed, runJson, launchSettings)} Hello from Program Message: 'PropertiesLaunchSettingsJson2' """);