// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.Build.Execution; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools.MSBuild; namespace Microsoft.DotNet.Tools.Run { public partial class RunCommand { public string Configuration { get; set; } public string Framework { get; set; } public string Project { get; set; } public IReadOnlyList Args { get; set; } private List _args; public RunCommand() { } public int Start() { Initialize(); EnsureProjectIsBuilt(); ICommand runCommand = GetRunCommand(); return runCommand .Execute() .ExitCode; } private void EnsureProjectIsBuilt() { List buildArgs = new List(); buildArgs.Add(Project); buildArgs.Add("/nologo"); buildArgs.Add("/verbosity:quiet"); if (!string.IsNullOrWhiteSpace(Configuration)) { buildArgs.Add($"/p:Configuration={Configuration}"); } if (!string.IsNullOrWhiteSpace(Framework)) { buildArgs.Add($"/p:TargetFramework={Framework}"); } var buildResult = new MSBuildForwardingApp(buildArgs).Execute(); if (buildResult != 0) { Reporter.Error.WriteLine(); throw new GracefulException("The build failed. Please fix the build errors and run again."); } } private ICommand GetRunCommand() { Dictionary globalProperties = new Dictionary() { { "MSBuildExtensionsPath", AppContext.BaseDirectory } }; if (!string.IsNullOrWhiteSpace(Configuration)) { globalProperties.Add("Configuration", Configuration); } if (!string.IsNullOrWhiteSpace(Framework)) { globalProperties.Add("TargetFramework", Framework); } ProjectInstance projectInstance = new ProjectInstance(Project, globalProperties, null); string runProgram = projectInstance.GetPropertyValue("RunCommand"); if (string.IsNullOrEmpty(runProgram)) { string outputType = projectInstance.GetPropertyValue("OutputType"); throw new GracefulException(string.Join(Environment.NewLine, "Unable to run your project.", "Please ensure you have a runnable project type and ensure 'dotnet run' supports this project.", $"The current OutputType is '{outputType}'.")); } string runArguments = projectInstance.GetPropertyValue("RunArguments"); string runWorkingDirectory = projectInstance.GetPropertyValue("RunWorkingDirectory"); string fullArguments = runArguments; if (_args.Any()) { fullArguments += " " + ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(_args); } CommandSpec commandSpec = new CommandSpec(runProgram, fullArguments, CommandResolutionStrategy.None); return Command.Create(commandSpec) .WorkingDirectory(runWorkingDirectory); } private void Initialize() { if (string.IsNullOrWhiteSpace(Project)) { string directory = Directory.GetCurrentDirectory(); string[] projectFiles = Directory.GetFiles(directory, "*.*proj"); if (projectFiles.Length == 0) { throw new InvalidOperationException( $"Couldn't find a project to run. Ensure a project exists in {directory}." + Environment.NewLine + "Or pass the path to the project using --project"); } else if (projectFiles.Length > 1) { throw new InvalidOperationException( $"Specify which project file to use because this '{directory}' contains more than one project file."); } Project = projectFiles[0]; } if (Args == null) { _args = new List(); } else { _args = new List(Args); } } } }