Port #4403 back into the main source code.

This change was lost when we converted the MSBuild "run3" verb to just "run".

Fix #6076
This commit is contained in:
Eric Erhardt 2017-03-21 13:46:08 -05:00
parent 1574349a59
commit 55eb812664
5 changed files with 71 additions and 38 deletions

View file

@ -1,13 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), testAsset.props))\testAsset.props" /> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), testAsset.props))\testAsset.props" />
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFrameworks>net451;netcoreapp2.0</TargetFrameworks> <TargetFrameworks>net451;netcoreapp2.0</TargetFrameworks>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(CLI_SharedFrameworkVersion)</RuntimeFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">
<PackageReference Include="Microsoft.NETCore.App" Version="$(CLI_SharedFrameworkVersion)" />
</ItemGroup>
</Project> </Project>

View file

@ -15,25 +15,19 @@ namespace Microsoft.DotNet.Tools.Run
public const string CommandOptionFrameworkDescription = "Build and run the app using the specified framework. The framework has to be specified in the project file. "; public const string CommandOptionFrameworkDescription = "Build and run the app using the specified framework. The framework has to be specified in the project file. ";
public const string CommandOptionNoBuild = "Do not build the project before running.";
public const string CommandOptionProjectDescription = "The path to the project file to run (defaults to the current directory if there is only one project)."; public const string CommandOptionProjectDescription = "The path to the project file to run (defaults to the current directory if there is only one project).";
public const string RunCommandException = "The build failed. Please fix the build errors and run again."; public const string RunCommandException = "The build failed. Please fix the build errors and run again.";
public const string RunCommandExceptionUnableToRunSpecifyFramework = "Unable to run your project\nYour project targets multiple frameworks. Please specify which framework to run using '{0}'.";
public const string RunCommandExceptionUnableToRun = "Unable to run your project\nPlease ensure you have a runnable project type and ensure '{0}' supports this project.\nThe current {1} is '{2}'"; public const string RunCommandExceptionUnableToRun = "Unable to run your project\nPlease ensure you have a runnable project type and ensure '{0}' supports this project.\nThe current {1} is '{2}'";
public const string RunCommandExceptionUnableToRun1 = "Unable to run your project."; public const string RunCommandExceptionNoProjects = "Couldn't find a project to run. Ensure a project exists in {0}, or pass the path to the project using {1}.";
public const string RunCommandExceptionUnableToRun2 = "Please ensure you have a runnable project type and ensure 'dotnet run' supports this project."; public const string RunCommandExceptionMultipleProjects = "Specify which project file to use because {0} contains more than one project file.";
public const string RunCommandExceptionUnableToRun3 = "The current OutputType is ";
public const string RunCommandInvalidOperationException1 = "Couldn't find a project to run. Ensure a project exists in ";
public const string RunCommandInvalidOperationException2 = "Or pass the path to the project using --project";
public const string RunCommandInvalidOperationException3 = "Specify which project file to use because this ";
public const string RunCommandInvalidOperationException4 = "contains more than one project file.";
public const string RunCommandAdditionalArgsHelpText = "Arguments passed to the application that is being run."; public const string RunCommandAdditionalArgsHelpText = "Arguments passed to the application that is being run.";
} }

View file

@ -28,6 +28,9 @@ namespace Microsoft.DotNet.Tools.Run
CommandOption framework = app.Option( CommandOption framework = app.Option(
$"-f|--framework <{LocalizableStrings.CommandOptionFramework}>", LocalizableStrings.CommandOptionFrameworkDescription, $"-f|--framework <{LocalizableStrings.CommandOptionFramework}>", LocalizableStrings.CommandOptionFrameworkDescription,
CommandOptionType.SingleValue); CommandOptionType.SingleValue);
CommandOption noBuild = app.Option(
"--no-build", LocalizableStrings.CommandOptionNoBuild,
CommandOptionType.BoolValue);
CommandOption project = app.Option( CommandOption project = app.Option(
"-p|--project", LocalizableStrings.CommandOptionProjectDescription, "-p|--project", LocalizableStrings.CommandOptionProjectDescription,
CommandOptionType.SingleValue); CommandOptionType.SingleValue);
@ -38,6 +41,7 @@ namespace Microsoft.DotNet.Tools.Run
runCmd.Configuration = configuration.Value(); runCmd.Configuration = configuration.Value();
runCmd.Framework = framework.Value(); runCmd.Framework = framework.Value();
runCmd.NoBuild = noBuild.BoolValue ?? false;
runCmd.Project = project.Value(); runCmd.Project = project.Value();
runCmd.Args = app.RemainingArguments; runCmd.Args = app.RemainingArguments;

View file

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Microsoft.Build.Execution; using Microsoft.Build.Evaluation;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.MSBuild; using Microsoft.DotNet.Tools.MSBuild;
@ -15,10 +15,12 @@ namespace Microsoft.DotNet.Tools.Run
{ {
public string Configuration { get; set; } public string Configuration { get; set; }
public string Framework { get; set; } public string Framework { get; set; }
public bool NoBuild { get; set; }
public string Project { get; set; } public string Project { get; set; }
public IReadOnlyList<string> Args { get; set; } public IReadOnlyList<string> Args { get; set; }
private List<string> _args; private List<string> _args;
private bool ShouldBuild => !NoBuild;
public RunCommand() public RunCommand()
{ {
@ -28,7 +30,10 @@ namespace Microsoft.DotNet.Tools.Run
{ {
Initialize(); Initialize();
EnsureProjectIsBuilt(); if (ShouldBuild)
{
EnsureProjectIsBuilt();
}
ICommand runCommand = GetRunCommand(); ICommand runCommand = GetRunCommand();
@ -40,9 +45,9 @@ namespace Microsoft.DotNet.Tools.Run
private void EnsureProjectIsBuilt() private void EnsureProjectIsBuilt()
{ {
List<string> buildArgs = new List<string>(); List<string> buildArgs = new List<string>();
buildArgs.Add(Project); buildArgs.Add(Project);
buildArgs.Add("/nologo"); buildArgs.Add("/nologo");
buildArgs.Add("/verbosity:quiet"); buildArgs.Add("/verbosity:quiet");
@ -82,23 +87,16 @@ namespace Microsoft.DotNet.Tools.Run
globalProperties.Add("TargetFramework", Framework); globalProperties.Add("TargetFramework", Framework);
} }
ProjectInstance projectInstance = new ProjectInstance(Project, globalProperties, null); Project project = new Project(Project, globalProperties, null);
string runProgram = projectInstance.GetPropertyValue("RunCommand"); string runProgram = project.GetPropertyValue("RunCommand");
if (string.IsNullOrEmpty(runProgram)) if (string.IsNullOrEmpty(runProgram))
{ {
string outputType = projectInstance.GetPropertyValue("OutputType"); ThrowUnableToRunError(project);
throw new GracefulException(
string.Format(
LocalizableStrings.RunCommandExceptionUnableToRun,
"dotnet run",
"OutputType",
outputType));
} }
string runArguments = projectInstance.GetPropertyValue("RunArguments"); string runArguments = project.GetPropertyValue("RunArguments");
string runWorkingDirectory = projectInstance.GetPropertyValue("RunWorkingDirectory"); string runWorkingDirectory = project.GetPropertyValue("RunWorkingDirectory");
string fullArguments = runArguments; string fullArguments = runArguments;
if (_args.Any()) if (_args.Any())
@ -112,6 +110,30 @@ namespace Microsoft.DotNet.Tools.Run
.WorkingDirectory(runWorkingDirectory); .WorkingDirectory(runWorkingDirectory);
} }
private void ThrowUnableToRunError(Project project)
{
string targetFrameworks = project.GetPropertyValue("TargetFrameworks");
if (!string.IsNullOrEmpty(targetFrameworks))
{
string targetFramework = project.GetPropertyValue("TargetFramework");
if (string.IsNullOrEmpty(targetFramework))
{
var framework = "--framework";
throw new GracefulException(LocalizableStrings.RunCommandExceptionUnableToRunSpecifyFramework, framework);
}
}
string outputType = project.GetPropertyValue("OutputType");
throw new GracefulException(
string.Format(
LocalizableStrings.RunCommandExceptionUnableToRun,
"dotnet run",
"OutputType",
outputType));
}
private void Initialize() private void Initialize()
{ {
if (string.IsNullOrWhiteSpace(Project)) if (string.IsNullOrWhiteSpace(Project))
@ -123,13 +145,11 @@ namespace Microsoft.DotNet.Tools.Run
{ {
var project = "--project"; var project = "--project";
throw new InvalidOperationException( throw new GracefulException(LocalizableStrings.RunCommandExceptionNoProjects, directory, project);
$"Couldn't find a project to run. Ensure a project exists in {directory}, or pass the path to the project using {project}");
} }
else if (projectFiles.Length > 1) else if (projectFiles.Length > 1)
{ {
throw new InvalidOperationException( throw new GracefulException(LocalizableStrings.RunCommandExceptionMultipleProjects, directory);
$"Specify which project file to use because {directory} contains more than one project file.");
} }
Project = projectFiles[0]; Project = projectFiles[0];

View file

@ -145,5 +145,23 @@ namespace Microsoft.DotNet.Cli.Run.Tests
.Should().Pass() .Should().Pass()
.And.HaveStdOutContaining("Hello World"); .And.HaveStdOutContaining("Hello World");
} }
[Fact]
public void ItReportsAGoodErrorWhenProjectHasMultipleFrameworks()
{
var testAppName = "MSBuildAppWithMultipleFrameworks";
var testInstance = TestAssets.Get(testAppName)
.CreateInstance()
.WithSourceFiles()
.WithRestoreFiles();
// use --no-build so this test can run on all platforms.
// the test app targets net451, which can't be built on non-Windows
new RunCommand()
.WithWorkingDirectory(testInstance.Root)
.ExecuteWithCapturedOutput("--no-build")
.Should().Fail()
.And.HaveStdErrContaining("--framework");
}
} }
} }