diff --git a/.editorconfig b/.editorconfig
index bc17bbe69267..e35b5cd19b0f 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -511,11 +511,11 @@ dotnet_diagnostic.IDE0040.severity = warning
insert_final_newline = false
# Verify settings
-[*.{received,verified}.{txt,xml,json}]
+[*.{received,verified}.{txt,xml,json,sh,zsh,nu,fish,ps1}]
charset = "utf-8-bom"
end_of_line = lf
indent_size = unset
indent_style = unset
insert_final_newline = false
tab_width = unset
-trim_trailing_whitespace = false
\ No newline at end of file
+trim_trailing_whitespace = false
diff --git a/.gitattributes b/.gitattributes
index 2f46e347155a..a7c35ea1b75a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -67,3 +67,7 @@
*.verified.txt text eol=lf working-tree-encoding=UTF-8
*.verified.xml text eol=lf working-tree-encoding=UTF-8
*.verified.json text eol=lf working-tree-encoding=UTF-8
+*.verified.sh text eol=lf working-tree-encoding=UTF-8
+*.verified.zsh text eol=lf working-tree-encoding=UTF-8
+*.verified.nu text eol=lf working-tree-encoding=UTF-8
+*.verified.fish text eol=lf working-tree-encoding=UTF-8
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1cdcc7c1869e..212ebd955c26 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,11 @@
{
"dotnet.testWindow.disableAutoDiscovery": true,
- "dotnet.defaultSolution": "sdk.slnx"
+ "dotnet.testWindow.disableBuildOnRun": true,
+ "dotnet.defaultSolution": "cli.slnf",
+ "files.associations": {
+ "*.slnf": "json",
+ "*.props": "xml",
+ "*.targets": "xml",
+ "*.*proj": "xml"
+ }
}
diff --git a/cli.slnf b/cli.slnf
new file mode 100644
index 000000000000..a300800156bf
--- /dev/null
+++ b/cli.slnf
@@ -0,0 +1,15 @@
+{
+ "solution": {
+ "path": "sdk.slnx",
+ "projects": [
+ "src\\BuiltInTools\\dotnet-watch\\dotnet-watch.csproj",
+ "src\\Cli\\dotnet\\dotnet.csproj",
+ "src\\Cli\\Microsoft.DotNet.Cli.Utils\\Microsoft.DotNet.Cli.Utils.csproj",
+ "test\\dotnet-new.IntegrationTests\\dotnet-new.IntegrationTests.csproj",
+ "test\\dotnet-watch.Tests\\dotnet-watch.Tests.csproj",
+ "test\\dotnet.Tests\\dotnet.Tests.csproj",
+ "test\\Microsoft.DotNet.Cli.Utils.Tests\\Microsoft.DotNet.Cli.Utils.Tests.csproj",
+ "test\\Microsoft.NET.TestFramework\\Microsoft.NET.TestFramework.csproj"
+ ]
+ }
+}
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/Env.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/Env.cs
index dbedb133bfc0..c85eaa1d0bf7 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/Env.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/Env.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+
namespace Microsoft.DotNet.Cli.Utils;
public static class Env
@@ -21,6 +23,9 @@ public static class Env
public static bool GetEnvironmentVariableAsBool(string name, bool defaultValue = false) =>
s_environment.GetEnvironmentVariableAsBool(name, defaultValue);
+ public static bool TryGetEnvironmentVariableAsBool(string name, [NotNullWhen(true)] out bool value) =>
+ s_environment.TryGetEnvironmentVariableAsBool(name, out value);
+
public static int? GetEnvironmentVariableAsNullableInt(string name) =>
s_environment.GetEnvironmentVariableAsNullableInt(name);
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs
index 50984a692d1c..06c64b67110a 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using Microsoft.DotNet.Cli.Utils.Extensions;
namespace Microsoft.DotNet.Cli.Utils;
@@ -136,6 +137,12 @@ public bool GetEnvironmentVariableAsBool(string name, bool defaultValue)
return Environment.GetEnvironmentVariable(variable, target);
}
+ public bool TryGetEnvironmentVariable(string name, [NotNullWhen(true)] out string? value)
+ {
+ value = Environment.GetEnvironmentVariable(name);
+ return value != null;
+ }
+
public void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target)
{
Environment.SetEnvironmentVariable(variable, value, target);
@@ -150,4 +157,57 @@ public void SetEnvironmentVariable(string variable, string value, EnvironmentVar
return null;
}
+
+ public bool TryGetEnvironmentVariableAsBool(string name, [NotNullWhen(true)] out bool value)
+ {
+ if (TryGetEnvironmentVariable(name, out string? strValue) &&
+ (bool.TryParse(strValue, out bool boolValue)
+ || TryParseNonBoolConstantStringAsBool(strValue, out boolValue)))
+ {
+ value = boolValue;
+ return true;
+ }
+ else
+ {
+ value = false;
+ return false;
+ }
+ }
+
+ ///
+ /// Parses non-boolean constant strings like "1", "0", "yes", "no", "on", "off" as boolean values.
+ ///
+ private static bool TryParseNonBoolConstantStringAsBool(string? strValue, out bool value)
+ {
+ switch (strValue?.ToLowerInvariant())
+ {
+ case "1":
+ case "yes":
+ case "on":
+ value = true;
+ return true;
+ case "0":
+ case "no":
+ case "off":
+ value = false;
+ return true;
+ default:
+ value = false;
+ return false;
+ }
+ }
+
+ public bool TryGetEnvironmentVariableAsInt(string name, [NotNullWhen(true)] out int value)
+ {
+ if (TryGetEnvironmentVariable(name, out string? strValue) && int.TryParse(strValue, out int intValue))
+ {
+ value = intValue;
+ return true;
+ }
+ else
+ {
+ value = -1;
+ return false;
+ }
+ }
}
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs
index 385f989d4990..8aaacf30fbad 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs
@@ -3,6 +3,9 @@
namespace Microsoft.DotNet.Cli.Utils;
+using System.Diagnostics.CodeAnalysis;
+
+
public interface IEnvironmentProvider
{
IEnumerable ExecutableExtensions { get; }
@@ -19,6 +22,10 @@ public interface IEnvironmentProvider
string? GetEnvironmentVariable(string name);
+ bool TryGetEnvironmentVariable(string name, [NotNullWhen(true)] out string? value);
+ bool TryGetEnvironmentVariableAsBool(string name, [NotNullWhen(true)] out bool value);
+ bool TryGetEnvironmentVariableAsInt(string name, [NotNullWhen(true)] out int value);
+
string? GetEnvironmentVariable(string variable, EnvironmentVariableTarget target);
void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target);
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs
index 12226f42f0d6..7fedc17f3878 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs
@@ -21,7 +21,9 @@ private MSBuildArgs(
string[]? getTargetResult,
string[]? getResultOutputFile,
VerbosityOptions? verbosity,
- string[]? otherMSBuildArgs)
+ bool noLogo,
+ string[]? otherMSBuildArgs
+ )
{
GlobalProperties = properties;
RestoreGlobalProperties = restoreProperties;
@@ -31,6 +33,7 @@ private MSBuildArgs(
GetTargetResult = getTargetResult;
GetResultOutputFile = getResultOutputFile;
Verbosity = verbosity;
+ NoLogo = noLogo;
OtherMSBuildArgs = otherMSBuildArgs is not null
? [.. otherMSBuildArgs]
: new List();
@@ -51,16 +54,33 @@ private MSBuildArgs(
///
public string[]? RequestedTargets { get; }
+ ///
+ /// If specified, the list of MSBuild Property names to retrieve and report directly for this build of a single project.
+ ///
public string[]? GetProperty { get; }
+ ///
+ /// If specified, the list of MSBuild Item names to retrieve and report directly for this build of a single project.
+ ///
public string[]? GetItem { get; }
+ ///
+ /// If specified, the list of MSBuild Target Output/Return Items to retrieve and report directly for this build of a single project.
+ ///
public string[]? GetTargetResult { get; }
+ ///
+ /// If specified, the list of output files to which to write --getProperty, --getItem, and --getTargetResult outputs.
+ ///
public string[]? GetResultOutputFile { get; }
public VerbosityOptions? Verbosity { get; }
+ ///
+ /// Whether or not the MSBuild product header text should be emitted at the start of this build
+ ///
+ public bool NoLogo { get; }
+
///
/// All other arguments that aren't already explicitly modeled by this structure.
/// The main categories of these today are logger configurations
@@ -89,16 +109,15 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable forwardedA
}
var parseResult = fakeCommand.Parse([.. forwardedAndUserFacingArgs], _analysisParsingConfiguration);
- var globalProperties = parseResult.GetResult("--property") is OptionResult propResult ? propResult.GetValueOrDefault?>() : null;
- var restoreProperties = parseResult.GetResult("--restoreProperty") is OptionResult restoreResult ? restoreResult.GetValueOrDefault?>() : null;
- var requestedTargets = parseResult.GetResult("--target") is OptionResult targetResult ? targetResult.GetValueOrDefault() : null;
+ var globalProperties = TryGetValue?>("--property");
+ var restoreProperties = TryGetValue?>("--restoreProperty");
+ var requestedTargets = TryGetValue("--target");
var getProperty = TryGetValue("--getProperty");
var getItem = TryGetValue("--getItem");
var getTargetResult = TryGetValue("--getTargetResult");
var getResultOutputFile = TryGetValue("--getResultOutputFile");
- var verbosity = parseResult.GetResult("--verbosity") is OptionResult verbosityResult
- ? verbosityResult.GetValueOrDefault()
- : null;
+ var verbosity = TryGetValue("--verbosity");
+ var nologo = TryGetValue("--no-logo") ?? true; // Default to nologo if not specified
var otherMSBuildArgs = parseResult.UnmatchedTokens.ToArray();
return new MSBuildArgs(
properties: globalProperties,
@@ -109,8 +128,12 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable forwardedA
getTargetResult: getTargetResult,
getResultOutputFile: getResultOutputFile,
otherMSBuildArgs: otherMSBuildArgs,
- verbosity: verbosity);
+ verbosity: verbosity,
+ noLogo: nologo);
+ /// We can't use to check if the names of the options we care
+ /// about were specified, because if they weren't specified it throws.
+ /// So we first check if the option was specified, and only then get its value.
T? TryGetValue(string name)
{
return options.Any(o => o.Name == name) ? parseResult.GetValue(name) : default;
@@ -120,19 +143,19 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable forwardedA
public static MSBuildArgs FromProperties(ReadOnlyDictionary? properties)
{
- return new MSBuildArgs(properties, null, null, null, null, null, null, null, null);
+ return new MSBuildArgs(properties, null, null, null, null, null, null, null, noLogo: false, null);
}
public static MSBuildArgs FromOtherArgs(params ReadOnlySpan args)
{
- return new MSBuildArgs(null, null, null, null, null, null, null, null, args.ToArray());
+ return new MSBuildArgs(null, null, null, null, null, null, null, null, noLogo: false, args.ToArray());
}
public static MSBuildArgs FromVerbosity(VerbosityOptions verbosity)
{
- return new MSBuildArgs(null, null, null, null, null, null, null, verbosity, null);
+ return new MSBuildArgs(null, null, null, null, null, null, null, verbosity, noLogo: false, null);
}
- public static readonly MSBuildArgs ForHelp = new(null, null, null, null, null, null, null, null, ["--help"]);
+ public static readonly MSBuildArgs ForHelp = new(null, null, null, null, null, null, null, null, noLogo: true, ["--help"]);
///
/// Completely replaces the MSBuild arguments with the provided .
@@ -148,6 +171,7 @@ public MSBuildArgs CloneWithExplicitArgs(string[] newArgs)
getTargetResult: GetTargetResult,
getResultOutputFile: GetResultOutputFile,
otherMSBuildArgs: newArgs,
+ noLogo: NoLogo,
verbosity: Verbosity);
}
@@ -168,6 +192,7 @@ public MSBuildArgs CloneWithAdditionalArgs(params string[] additionalArgs)
GetTargetResult,
GetResultOutputFile,
Verbosity,
+ NoLogo,
OtherMSBuildArgs.ToArray());
}
@@ -180,6 +205,7 @@ public MSBuildArgs CloneWithAdditionalArgs(params string[] additionalArgs)
GetTargetResult,
GetResultOutputFile,
Verbosity,
+ NoLogo,
[.. OtherMSBuildArgs, .. additionalArgs]);
}
@@ -197,6 +223,7 @@ public MSBuildArgs CloneWithAdditionalRestoreProperties(ReadOnlyDictionary additi
GetTargetResult,
GetResultOutputFile,
Verbosity,
+ NoLogo,
OtherMSBuildArgs.ToArray());
}
@@ -305,6 +338,22 @@ public MSBuildArgs CloneWithVerbosity(VerbosityOptions newVerbosity)
GetTargetResult,
GetResultOutputFile,
newVerbosity,
+ NoLogo,
+ OtherMSBuildArgs.ToArray());
+ }
+
+ public MSBuildArgs CloneWithNoLogo(bool noLogo)
+ {
+ return new MSBuildArgs(
+ GlobalProperties,
+ RestoreGlobalProperties,
+ RequestedTargets,
+ GetProperty,
+ GetItem,
+ GetTargetResult,
+ GetResultOutputFile,
+ Verbosity,
+ noLogo,
OtherMSBuildArgs.ToArray());
}
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildForwardingAppWithoutLogging.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildForwardingAppWithoutLogging.cs
index e0dca709ac3c..87d021eda157 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildForwardingAppWithoutLogging.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildForwardingAppWithoutLogging.cs
@@ -44,17 +44,11 @@ public static string MSBuildVersion
private readonly List _msbuildRequiredParameters = ["-maxcpucount", $"--verbosity:{DefaultVerbosity}"];
- public MSBuildForwardingAppWithoutLogging(MSBuildArgs msbuildArgs, string? msbuildPath = null, bool includeLogo = false, bool isRestoring = true)
+ public MSBuildForwardingAppWithoutLogging(MSBuildArgs msbuildArgs, string? msbuildPath = null)
{
string defaultMSBuildPath = GetMSBuildExePath();
_msbuildArgs = msbuildArgs;
- if (!includeLogo && !msbuildArgs.OtherMSBuildArgs.Contains("-nologo", StringComparer.OrdinalIgnoreCase))
- {
- // If the user didn't explicitly ask for -nologo, we add it to avoid the MSBuild logo.
- // This is useful for scenarios like restore where we don't want to print the logo.
- // Note that this is different from the default behavior of MSBuild, which prints the logo.
- msbuildArgs.OtherMSBuildArgs.Add("-nologo");
- }
+
string? tlpDefault = TerminalLoggerDefault;
if (string.IsNullOrWhiteSpace(tlpDefault))
{
@@ -101,6 +95,7 @@ private string[] EmitMSBuildArgs(MSBuildArgs msbuildArgs) => [
.. msbuildArgs.RestoreGlobalProperties?.Select(kvp => EmitProperty(kvp, "restoreProperty")) ?? [],
.. msbuildArgs.RequestedTargets?.Select(target => $"--target:{target}") ?? [],
.. msbuildArgs.Verbosity is not null ? new string[1] { $"--verbosity:{msbuildArgs.Verbosity}" } : [],
+ .. msbuildArgs.NoLogo is true ? new string[1] { "--nologo" } : [],
.. msbuildArgs.OtherMSBuildArgs
];
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/Polyfills.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/Polyfills.cs
index ab674a2906ee..59668dbae394 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/Polyfills.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/Polyfills.cs
@@ -4,11 +4,24 @@
#if NET472
#pragma warning disable IDE0130 // Namespace does not match folder structure
-namespace System.Runtime.CompilerServices;
-#pragma warning restore IDE0130 // Namespace does not match folder structure
+namespace System.Runtime.CompilerServices {
+
+ internal static class IsExternalInit
+ {
+ }
+
+}
-internal static class IsExternalInit
+namespace System.Diagnostics.CodeAnalysis
{
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ internal sealed class NotNullWhenAttribute : Attribute
+ {
+ public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
+
+ public bool ReturnValue { get; }
+ }
}
+#pragma warning restore IDE0130 // Namespace does not match folder structure
#endif
diff --git a/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs b/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs
index 2f8bb7badd98..aa844850e316 100644
--- a/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs
+++ b/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs
@@ -385,7 +385,7 @@ internal void GenerateDepsJsonFile(
string? stdOut;
string? stdErr;
- var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments([..args], CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandParser.TargetOption, BuildCommandParser.VerbosityOption);
+ var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments([..args], CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandParser.TargetOption, BuildCommandParser.VerbosityOption, BuildCommandParser.NoLogoOption);
var forwardingAppWithoutLogging = new MSBuildForwardingAppWithoutLogging(msbuildArgs, msBuildExePath);
if (forwardingAppWithoutLogging.ExecuteMSBuildOutOfProc)
{
diff --git a/src/Cli/dotnet/Commands/Build/BuildCommand.cs b/src/Cli/dotnet/Commands/Build/BuildCommand.cs
index 3d8943315a94..264abdad7d80 100644
--- a/src/Cli/dotnet/Commands/Build/BuildCommand.cs
+++ b/src/Cli/dotnet/Commands/Build/BuildCommand.cs
@@ -43,7 +43,7 @@ public static CommandBase FromParseResult(ParseResult parseResult, string? msbui
noRestore: noRestore,
msbuildPath: msbuildPath
),
- [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandParser.TargetOption, BuildCommandParser.VerbosityOption],
+ [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandParser.TargetOption, BuildCommandParser.VerbosityOption, BuildCommandParser.NoLogoOption],
parseResult,
msbuildPath
);
diff --git a/src/Cli/dotnet/Commands/Build/BuildCommandParser.cs b/src/Cli/dotnet/Commands/Build/BuildCommandParser.cs
index 74b4efa2a712..be2e52c45263 100644
--- a/src/Cli/dotnet/Commands/Build/BuildCommandParser.cs
+++ b/src/Cli/dotnet/Commands/Build/BuildCommandParser.cs
@@ -36,11 +36,7 @@ internal static class BuildCommandParser
Arity = ArgumentArity.Zero
}.ForwardAs("--property:BuildProjectReferences=false");
- public static readonly Option NoLogoOption = new Option("--nologo")
- {
- Description = CliCommandStrings.BuildCmdNoLogo,
- Arity = ArgumentArity.Zero
- }.ForwardAs("-nologo");
+ public static readonly Option NoLogoOption = CommonOptions.NoLogoOption();
public static readonly Option NoRestoreOption = CommonOptions.NoRestoreOption;
diff --git a/src/Cli/dotnet/Commands/Clean/CleanCommand.cs b/src/Cli/dotnet/Commands/Clean/CleanCommand.cs
index 1290b8b68cfd..c7e48c376ee9 100644
--- a/src/Cli/dotnet/Commands/Clean/CleanCommand.cs
+++ b/src/Cli/dotnet/Commands/Clean/CleanCommand.cs
@@ -33,7 +33,7 @@ public static CommandBase FromParseResult(ParseResult result, string? msbuildPat
NoWriteBuildMarkers = true,
},
static (msbuildArgs, msbuildPath) => new CleanCommand(msbuildArgs, msbuildPath),
- [ CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, CleanCommandParser.TargetOption, CleanCommandParser.VerbosityOption ],
+ [ CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, CleanCommandParser.TargetOption, CleanCommandParser.VerbosityOption, CleanCommandParser.NoLogoOption],
result,
msbuildPath
);
diff --git a/src/Cli/dotnet/Commands/Clean/CleanCommandParser.cs b/src/Cli/dotnet/Commands/Clean/CleanCommandParser.cs
index 24e83acc8b64..117537d7fd1f 100644
--- a/src/Cli/dotnet/Commands/Clean/CleanCommandParser.cs
+++ b/src/Cli/dotnet/Commands/Clean/CleanCommandParser.cs
@@ -24,15 +24,11 @@ internal static class CleanCommandParser
HelpName = CliCommandStrings.CleanCmdOutputDir
}.ForwardAsOutputPath("OutputPath");
- public static readonly Option NoLogoOption = new Option("--nologo")
- {
- Description = CliCommandStrings.CleanCmdNoLogo,
- Arity = ArgumentArity.Zero
- }.ForwardAs("-nologo");
+ public static readonly Option NoLogoOption = CommonOptions.NoLogoOption();
- public static readonly Option FrameworkOption = CommonOptions.FrameworkOption(CliCommandStrings.CleanFrameworkOptionDescription);
+ public static readonly Option FrameworkOption = CommonOptions.FrameworkOption(CliCommandStrings.CleanFrameworkOptionDescription);
- public static readonly Option ConfigurationOption = CommonOptions.ConfigurationOption(CliCommandStrings.CleanConfigurationOptionDescription);
+ public static readonly Option ConfigurationOption = CommonOptions.ConfigurationOption(CliCommandStrings.CleanConfigurationOptionDescription);
public static readonly Option TargetOption = CommonOptions.RequiredMSBuildTargetOption("Clean");
diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx
index 4fbcfb5e5d2b..2c94953811c9 100644
--- a/src/Cli/dotnet/Commands/CliCommandStrings.resx
+++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx
@@ -1,17 +1,17 @@
-
@@ -166,7 +166,7 @@
.NET Builder
-
+
Do not display the startup banner or the copyright message.
@@ -250,9 +250,6 @@ Paths searched: '{1}', '{2}'.
.NET Clean Command
-
- Do not display the startup banner or the copyright message.
-
OUTPUT_DIR
@@ -1322,9 +1319,6 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man
.NET Core NuGet Package Packer
-
- Do not display the startup banner or the copyright message.
-
OUTPUT_DIR
@@ -1597,9 +1591,6 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man
Publisher for the .NET Platform
-
- Do not display the startup banner or the copyright message.
-
The configuration to publish for. The default is 'Release' for NET 8.0 projects and above, but 'Debug' for older projects.
diff --git a/src/Cli/dotnet/Commands/MSBuild/MSBuildCommand.cs b/src/Cli/dotnet/Commands/MSBuild/MSBuildCommand.cs
index d7edaea57478..7e28945067a3 100644
--- a/src/Cli/dotnet/Commands/MSBuild/MSBuildCommand.cs
+++ b/src/Cli/dotnet/Commands/MSBuild/MSBuildCommand.cs
@@ -11,7 +11,17 @@ namespace Microsoft.DotNet.Cli.Commands.MSBuild;
public class MSBuildCommand(
IEnumerable msbuildArgs,
string? msbuildPath = null
-) : MSBuildForwardingApp(MSBuildArgs.AnalyzeMSBuildArguments([..msbuildArgs], CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, MSBuildCommandParser.TargetOption, CommonOptions.VerbosityOption()), msbuildPath, includeLogo: true)
+) : MSBuildForwardingApp(MSBuildArgs.AnalyzeMSBuildArguments(
+ [.. msbuildArgs],
+ CommonOptions.PropertiesOption,
+ CommonOptions.RestorePropertiesOption,
+ MSBuildCommandParser.TargetOption,
+ CommonOptions.VerbosityOption(),
+ // We set the no-logo option to false here to ensure that by default the logo is shown for this command.
+ // This is different from other commands that default to hiding the logo - but this command is meant to mimic
+ // the behavior of calling MSBuild directly, which shows the logo by default.
+ CommonOptions.NoLogoOption(false)
+ ), msbuildPath)
{
public static MSBuildCommand FromArgs(string[] args, string? msbuildPath = null)
{
diff --git a/src/Cli/dotnet/Commands/MSBuild/MSBuildForwardingApp.cs b/src/Cli/dotnet/Commands/MSBuild/MSBuildForwardingApp.cs
index 3055de0883f5..df0eaf4d166a 100644
--- a/src/Cli/dotnet/Commands/MSBuild/MSBuildForwardingApp.cs
+++ b/src/Cli/dotnet/Commands/MSBuild/MSBuildForwardingApp.cs
@@ -42,18 +42,17 @@ private static MSBuildArgs ConcatTelemetryLogger(MSBuildArgs msbuildArgs)
/// Mostly intended for quick/one-shot usage - most 'core' SDK commands should do more hands-on parsing.
///
public MSBuildForwardingApp(IEnumerable rawMSBuildArgs, string? msbuildPath = null) : this(
- MSBuildArgs.AnalyzeMSBuildArguments(rawMSBuildArgs.ToArray(), CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, CommonOptions.MSBuildTargetOption(), CommonOptions.VerbosityOption()),
+ MSBuildArgs.AnalyzeMSBuildArguments(rawMSBuildArgs.ToArray(), CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, CommonOptions.MSBuildTargetOption(), CommonOptions.VerbosityOption(), CommonOptions.NoLogoOption()),
msbuildPath)
{
}
- public MSBuildForwardingApp(MSBuildArgs msBuildArgs, string? msbuildPath = null, bool includeLogo = false)
+ public MSBuildForwardingApp(MSBuildArgs msBuildArgs, string? msbuildPath = null)
{
var modifiedMSBuildArgs = CommonRunHelpers.AdjustMSBuildForLLMs(ConcatTelemetryLogger(msBuildArgs));
_forwardingAppWithoutLogging = new MSBuildForwardingAppWithoutLogging(
modifiedMSBuildArgs,
- msbuildPath: msbuildPath,
- includeLogo: includeLogo);
+ msbuildPath: msbuildPath);
// Add the performance log location to the environment of the target process.
if (PerformanceLogManager.Instance != null && !string.IsNullOrEmpty(PerformanceLogManager.Instance.CurrentLogDirectory))
diff --git a/src/Cli/dotnet/Commands/New/DotnetCommandCallbacks.cs b/src/Cli/dotnet/Commands/New/DotnetCommandCallbacks.cs
index 46ddfe28c4b0..4aae2f0f037e 100644
--- a/src/Cli/dotnet/Commands/New/DotnetCommandCallbacks.cs
+++ b/src/Cli/dotnet/Commands/New/DotnetCommandCallbacks.cs
@@ -38,7 +38,7 @@ internal static bool RestoreProject(string pathToRestore)
{
PathUtility.EnsureAllPathsExist([pathToRestore], CliStrings.CommonFileNotFound, allowDirectories: true);
// for the implicit restore we do not want the terminal logger to emit any output unless there are errors
- return RestoreCommand.Run([pathToRestore, "-tlp:verbosity=quiet"]) == 0;
+ return RestoreCommand.Run([pathToRestore, "-tlp:verbosity=quiet", "--no-logo"]) == 0;
}
internal static bool AddProjectsToSolution(string solutionPath, IReadOnlyList projectsToAdd, string? solutionFolder, bool? inRoot)
diff --git a/src/Cli/dotnet/Commands/Pack/PackCommand.cs b/src/Cli/dotnet/Commands/Pack/PackCommand.cs
index 57342f67bad2..9f31bfa145fe 100644
--- a/src/Cli/dotnet/Commands/Pack/PackCommand.cs
+++ b/src/Cli/dotnet/Commands/Pack/PackCommand.cs
@@ -60,6 +60,7 @@ public static CommandBase FromParseResult(ParseResult parseResult, string? msbui
CommonOptions.RestorePropertiesOption,
PackCommandParser.TargetOption,
PackCommandParser.VerbosityOption,
+ PackCommandParser.NoLogoOption
],
parseResult,
msbuildPath,
diff --git a/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs b/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs
index a57aa2fabfcd..23fc1ef58f69 100644
--- a/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs
+++ b/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs
@@ -49,11 +49,7 @@ internal static class PackCommandParser
Arity = ArgumentArity.Zero
}.ForwardAs("-property:Serviceable=true");
- public static readonly Option NoLogoOption = new Option("--nologo")
- {
- Description = CliCommandStrings.PackCmdNoLogo,
- Arity = ArgumentArity.Zero
- }.ForwardAs("-nologo");
+ public static readonly Option NoLogoOption = CommonOptions.NoLogoOption();
public static readonly Option NoRestoreOption = CommonOptions.NoRestoreOption;
diff --git a/src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs b/src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs
index d6c1ef2f4afd..a463165828cb 100644
--- a/src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs
+++ b/src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs
@@ -91,7 +91,7 @@ private static void GetProjectDependencyGraph(string projectFilePath, string dgF
$"-property:RestoreDotnetCliToolReferences=false",
// Output should not include MSBuild version header
- "-nologo",
+ "--nologo",
// Set verbosity to quiet to avoid cluttering the output for this 'inner' build
"-v:quiet"
diff --git a/src/Cli/dotnet/Commands/Publish/PublishCommand.cs b/src/Cli/dotnet/Commands/Publish/PublishCommand.cs
index 2bfb835871a9..424a2250c25a 100644
--- a/src/Cli/dotnet/Commands/Publish/PublishCommand.cs
+++ b/src/Cli/dotnet/Commands/Publish/PublishCommand.cs
@@ -58,7 +58,7 @@ public static CommandBase FromParseResult(ParseResult parseResult, string? msbui
noRestore: noRestore,
msbuildPath: msbuildPath
),
- [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, PublishCommandParser.TargetOption, PublishCommandParser.VerbosityOption],
+ [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, PublishCommandParser.TargetOption, PublishCommandParser.VerbosityOption, PublishCommandParser.NoLogoOption],
parseResult,
msbuildPath,
(msbuildArgs) =>
diff --git a/src/Cli/dotnet/Commands/Publish/PublishCommandParser.cs b/src/Cli/dotnet/Commands/Publish/PublishCommandParser.cs
index 9fbe305d4877..2c2b1b20e36f 100644
--- a/src/Cli/dotnet/Commands/Publish/PublishCommandParser.cs
+++ b/src/Cli/dotnet/Commands/Publish/PublishCommandParser.cs
@@ -38,11 +38,7 @@ internal static class PublishCommandParser
Arity = ArgumentArity.Zero
}.ForwardAs("-property:NoBuild=true");
- public static readonly Option NoLogoOption = new Option("--nologo")
- {
- Description = CliCommandStrings.PublishCmdNoLogo,
- Arity = ArgumentArity.Zero
- }.ForwardAs("-nologo");
+ public static readonly Option NoLogoOption = CommonOptions.NoLogoOption();
public static readonly Option NoRestoreOption = CommonOptions.NoRestoreOption;
diff --git a/src/Cli/dotnet/Commands/Restore/RestoreCommand.cs b/src/Cli/dotnet/Commands/Restore/RestoreCommand.cs
index 6eb650b0e261..5a9ff6a37056 100644
--- a/src/Cli/dotnet/Commands/Restore/RestoreCommand.cs
+++ b/src/Cli/dotnet/Commands/Restore/RestoreCommand.cs
@@ -40,7 +40,7 @@ public static CommandBase FromParseResult(ParseResult result, string? msbuildPat
{
return CreateForwarding(msbuildArgs, msbuildPath);
},
- [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, RestoreCommandParser.TargetOption, RestoreCommandParser.VerbosityOption],
+ [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, RestoreCommandParser.TargetOption, RestoreCommandParser.VerbosityOption, RestoreCommandParser.NoLogoOption],
result,
msbuildPath
);
diff --git a/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs b/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs
index 7e1f4a48106d..f32a0b1545b7 100644
--- a/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs
+++ b/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs
@@ -27,36 +27,36 @@ internal static class RestoreCommandParser
public static readonly Option TargetOption = CommonOptions.RequiredMSBuildTargetOption("Restore");
public static readonly Option VerbosityOption = CommonOptions.VerbosityOption(Utils.VerbosityOptions.minimal);
-
- private static IEnumerable