diff --git a/TestAssets/TestPackages/dotnet-desktop-and-portable/Program.cs b/TestAssets/TestPackages/dotnet-desktop-and-portable/Program.cs index de299bfc4..0e67613a0 100644 --- a/TestAssets/TestPackages/dotnet-desktop-and-portable/Program.cs +++ b/TestAssets/TestPackages/dotnet-desktop-and-portable/Program.cs @@ -11,6 +11,7 @@ namespace ConsoleApplication #elif NETSTANDARD1_5 Console.WriteLine($"Hello {string.Join(" ", args)} From .NETStandardApp,Version=v1.5"); #endif + Console.WriteLine($"Base Directory - {AppContext.BaseDirectory}"); } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolutionStrategy.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolutionStrategy.cs index a819e9143..e239fccb6 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolutionStrategy.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolutionStrategy.cs @@ -23,6 +23,9 @@ // command loaded from rooted path RootedPath, + // command loaded from project build output path + OutputPath, + // command not found None } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/OutputPathCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/OutputPathCommandResolver.cs new file mode 100644 index 000000000..da7ce99b1 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/OutputPathCommandResolver.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class OutputPathCommandResolver : AbstractPathBasedCommandResolver + { + public OutputPathCommandResolver(IEnvironmentProvider environment, + IPlatformCommandSpecFactory commandSpecFactory) : base(environment, commandSpecFactory) + { } + + + internal override string ResolveCommandPath(CommandResolverArguments commandResolverArguments) + { + if (commandResolverArguments.Framework == null + || commandResolverArguments.ProjectDirectory == null + || commandResolverArguments.Configuration == null + || commandResolverArguments.CommandName == null) + { + return null; + } + + return ResolveFromProjectOutput( + commandResolverArguments.ProjectDirectory, + commandResolverArguments.Framework, + commandResolverArguments.Configuration, + commandResolverArguments.CommandName, + commandResolverArguments.CommandArguments.OrEmptyIfNull(), + commandResolverArguments.OutputPath, + commandResolverArguments.BuildBasePath); + } + + private string ResolveFromProjectOutput( + string projectDirectory, + NuGetFramework framework, + string configuration, + string commandName, + IEnumerable commandArguments, + string outputPath, + string buildBasePath) + { + var projectContext = GetProjectContextFromDirectory( + projectDirectory, + framework); + + if (projectContext == null) + { + return null; + } + + var buildOutputPath = projectContext.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeFiles.BasePath; + + return _environment.GetCommandPathFromRootPath(buildOutputPath, commandName); + } + + private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework) + { + if (directory == null || framework == null) + { + return null; + } + + var projectRootPath = directory; + + if (!File.Exists(Path.Combine(projectRootPath, Project.FileName))) + { + return null; + } + + var projectContext = ProjectContext.Create( + projectRootPath, + framework, + PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers()); + + if (projectContext.RuntimeIdentifier == null) + { + return null; + } + + return projectContext; + } + + internal override CommandResolutionStrategy GetCommandResolutionStrategy() + { + return CommandResolutionStrategy.OutputPath; + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/ProjectDependenciesCommandFactory.cs b/src/Microsoft.DotNet.Cli.Utils/ProjectDependenciesCommandFactory.cs index d825d2cf1..975c94081 100644 --- a/src/Microsoft.DotNet.Cli.Utils/ProjectDependenciesCommandFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/ProjectDependenciesCommandFactory.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; +using Microsoft.Extensions.PlatformAbstractions; using NuGet.Frameworks; namespace Microsoft.DotNet.Cli.Utils @@ -76,7 +77,7 @@ namespace Microsoft.DotNet.Cli.Utils ProjectDirectory = projectDirectory }; - var commandResolver = GetProjectDependenciesCommandResolver(); + var commandResolver = GetProjectDependenciesCommandResolver(framework); var commandSpec = commandResolver.Resolve(commandResolverArguments); if (commandSpec == null) @@ -87,12 +88,29 @@ namespace Microsoft.DotNet.Cli.Utils return commandSpec; } - private ICommandResolver GetProjectDependenciesCommandResolver() + private ICommandResolver GetProjectDependenciesCommandResolver(NuGetFramework framework) { var environment = new EnvironmentProvider(); - var packagedCommandSpecFactory = new PackagedCommandSpecFactory(); - return new ProjectDependenciesCommandResolver(environment, packagedCommandSpecFactory); + if (framework.IsDesktop()) + { + var platformCommandSpecFactory = default(IPlatformCommandSpecFactory); + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) + { + platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + } + else + { + platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); + } + + return new OutputPathCommandResolver(environment, platformCommandSpecFactory); + } + else + { + var packagedCommandSpecFactory = new PackagedCommandSpecFactory(); + return new ProjectDependenciesCommandResolver(environment, packagedCommandSpecFactory); + } } } }