Skip to content
6 changes: 6 additions & 0 deletions src/Cli/dotnet/Commands/Run/RunCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,12 @@ private static void ThrowUnableToRunError(ProjectInstance project)
? TryFindSingleProjectInDirectory(projectFileOrDirectoryPath)
: projectFileOrDirectoryPath;

// Check if the project file actually exists when it's specified as a direct file path
if (projectFilePath is not null && !emptyProjectOption && !File.Exists(projectFilePath))
{
throw new GracefulException(CliCommandStrings.CmdNonExistentFileErrorDescription, projectFilePath);
}

// If no project exists in the directory and no --project was given,
// try to resolve an entry-point file instead.
entryPointFilePath = projectFilePath is null && emptyProjectOption
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public GivenDotnetRunInvocation(ITestOutputHelper log)
[InlineData(new string[] { "-p", "prop1=true" }, new string[] { "--property:prop1=true" })]
[InlineData(new string[] { "-p", "prop1=true", "-p", "prop2=false" }, new string[] { "--property:prop1=true", "--property:prop2=false" })]
[InlineData(new string[] { "-p:prop1=true;prop2=false" }, new string[] { "--property:prop1=true", "--property:prop2=false" })]
[InlineData(new string[] { "-p", "MyProject.csproj", "-p:prop1=true" }, new string[] { "--property:prop1=true" })]
[InlineData(new string[] { "-p", "HelloWorld.csproj", "-p:prop1=true" }, new string[] { "--property:prop1=true" })]
[InlineData(new string[] { "--disable-build-servers" }, new string[] { "--property:UseRazorBuildServer=false", "--property:UseSharedCompilation=false", "/nodeReuse:false" })]
public void MsbuildInvocationIsCorrect(string[] args, string[] expectedArgs)
{
Expand Down
26 changes: 26 additions & 0 deletions test/dotnet.Tests/CommandTests/Run/GivenDotnetRunBuildsCsProj.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1008,5 +1008,31 @@ public void EnvOptionNotAppliedToBuild()
.And
.HaveStdOutContaining("env: Configuration=XYZ");
}

[Fact]
public void ItProvidesConsistentErrorMessageWhenProjectFileDoesNotExistWithNoBuild()
{
var tempDir = _testAssetsManager.CreateTestDirectory();
var nonExistentProject = Path.Combine(tempDir.Path, "nonexistent.csproj");

var result = new DotnetCommand(Log, "run")
.WithWorkingDirectory(tempDir.Path)
.Execute("--project", nonExistentProject, "--no-build");

result.Should().Fail();
if (!TestContext.IsLocalized())
{
// After the fix, we should get a clear error message about the file not existing
var stderr = result.StdErr;

// Should provide a clear error message about the project file not existing
var hasExpectedErrorMessage = stderr.Contains("does not exist") ||
stderr.Contains("not found") ||
stderr.Contains("cannot find") ||
stderr.Contains("could not find");

hasExpectedErrorMessage.Should().BeTrue($"Expected error message to clearly indicate file doesn't exist, but got: {stderr}");
}
}
}
}
9 changes: 8 additions & 1 deletion test/dotnet.Tests/CommandTests/Run/RunParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ public RunParserTests(ITestOutputHelper output)
[Fact]
public void RunParserCanGetArgumentFromDoubleDash()
{
var runCommand = RunCommand.FromArgs(new[] { "--project", "foo.csproj", "--", "foo" });
var tam = new TestAssetsManager(output);
var testAsset = tam.CopyTestAsset("HelloWorld").WithSource();
var newWorkingDir = testAsset.Path;

Directory.SetCurrentDirectory(newWorkingDir);
var projectPath = Path.Combine(newWorkingDir, "HelloWorld.csproj");

var runCommand = RunCommand.FromArgs(new[] { "--project", projectPath, "--", "foo" });
runCommand.ApplicationArgs.Single().Should().Be("foo");
}
}
Expand Down