Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/Cli/dotnet/Commands/CliCommandStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,22 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man
<data name="RunCommandExceptionNoProjects" xml:space="preserve">
<value>Couldn't find a project to run. Ensure a project exists in {0}, or pass the path to the project using {1}.</value>
</data>
<data name="RunCommandWarningFileArgumentPassedToProject" xml:space="preserve">
<value>Warning: '{0}' appears to be a file-based app but was passed as an argument to the project '{1}'. To run it as a file-based app, use 'dotnet run --file {0}'. To pass it as an application argument, use 'dotnet run -- {0}' to suppress this warning.</value>
<comment>{0} is the file path argument. {1} is the project file path.{Locked="dotnet run --file"}{Locked="dotnet run --"}</comment>
</data>
<data name="WarningFileArgumentPassedToMSBuild" xml:space="preserve">
<value>Warning: '{0}' appears to be a file-based app but was treated as an MSBuild argument. To treat it as a file-based app, use 'dotnet {1} {0}'.</value>
<comment>{0} is the file path argument. {1} is the command name (e.g. build, clean, publish).{Locked="dotnet"}</comment>
</data>
<data name="WarningCsFileArgumentPassedToMSBuild" xml:space="preserve">
<value>Warning: '{0}' looks like a file-based app but the file was not found, and it was treated as an MSBuild argument.</value>
<comment>{0} is the .cs file path argument.</comment>
</data>
<data name="RunCommandWarningCsFileArgumentPassedToProject" xml:space="preserve">
<value>Warning: '{0}' looks like a file-based app but the file was not found, and it was passed as an argument to the project '{1}'. To pass it as an application argument, use 'dotnet run -- {0}' to suppress this warning.</value>
<comment>{0} is the .cs file path argument. {1} is the project file path.{Locked="dotnet run --"}</comment>
</data>
<data name="RunCommandExceptionUnableToRun" xml:space="preserve">
<value>Unable to proceed with project '{0}'.
Ensure you have a runnable project type.
Expand Down
21 changes: 21 additions & 0 deletions src/Cli/dotnet/Commands/CommandFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Commands.Run;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli.Utils.Extensions;
using Microsoft.DotNet.ProjectTools;

namespace Microsoft.DotNet.Cli.Commands;
Expand Down Expand Up @@ -39,6 +40,26 @@ internal static CommandBase CreateVirtualOrPhysicalCommand(
}
else
{
// Warn if any argument looks like a file-based program entry point but we're falling back to MSBuild.
// This can happen when extra positional arguments prevent the single-arg file-based path from being taken,
// or when a .cs file doesn't exist (so IsValidEntryPointPath returns false).
foreach (var candidate in nonBinLogArgs)
{
if (VirtualProjectBuilder.IsValidEntryPointPath(candidate))
{
Reporter.Error.WriteLine(
string.Format(CliCommandStrings.WarningFileArgumentPassedToMSBuild, candidate, commandDefinition.Name).Yellow());
break;
}

if (candidate.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
{
Reporter.Error.WriteLine(
string.Format(CliCommandStrings.WarningCsFileArgumentPassedToMSBuild, candidate).Yellow());
break;
}
}

var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments([.. forwardedArgs, .. args], [.. optionsToUseWhenParsingMSBuildFlags]);
msbuildArgs = transformer?.Invoke(msbuildArgs) ?? msbuildArgs;
return createPhysicalCommand(msbuildArgs, msbuildPath);
Expand Down
35 changes: 35 additions & 0 deletions src/Cli/dotnet/Commands/Run/RunCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,41 @@ public static RunCommand FromParseResult(ParseResult parseResult)
ref args,
out string? entryPointFilePath);

// Warn if an argument looks like a file-based program entry point but we're falling back to project-based run.
// This helps users who accidentally run `dotnet run file.cs` in a directory containing a project file.
// Do not warn if --project or --file was explicitly specified.
// Only consider arguments that appear before '--' in the command line.
if (projectFilePath is not null && projectOption is null && fileOption is null && !readCodeFromStdin)
{
var argValuesBeforeDoubleDash = parseResult.Tokens
.TakeWhile(static t => t.Type != TokenType.DoubleDash)
.Where(static t => t.Type == TokenType.Argument)
.Select(static t => t.Value)
.ToHashSet();

foreach (var arg in args)
{
if (!argValuesBeforeDoubleDash.Contains(arg))
{
continue;
}

if (VirtualProjectBuilder.IsValidEntryPointPath(arg))
{
Reporter.Error.WriteLine(
string.Format(CliCommandStrings.RunCommandWarningFileArgumentPassedToProject, arg, projectFilePath).Yellow());
break;
}

if (arg.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
{
Reporter.Error.WriteLine(
string.Format(CliCommandStrings.RunCommandWarningCsFileArgumentPassedToProject, arg, projectFilePath).Yellow());
break;
}
}
}

bool noBuild = parseResult.HasOption(definition.NoBuildOption);
string launchProfile = parseResult.GetValue(definition.LaunchProfileOption) ?? string.Empty;

Expand Down
22 changes: 21 additions & 1 deletion src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 21 additions & 1 deletion src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 21 additions & 1 deletion src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading