diff --git a/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs b/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs index 32620e0d59..df4ab26aad 100644 --- a/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs +++ b/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs @@ -119,6 +119,11 @@ public static string GetRelativePath(DirectoryInfo directory, FileSystemInfo chi /// public static string GetRelativePath(string path1, string path2) { + if (!Path.IsPathRooted(path1) || !Path.IsPathRooted(path2)) + { + throw new ArgumentException("both paths need to be rooted/full path"); + } + return GetRelativePath(path1, path2, Path.DirectorySeparatorChar, true); } diff --git a/src/dotnet/ShellShim/AppHostShimMaker.cs b/src/dotnet/ShellShim/AppHostShimMaker.cs index 9b5eaf2de1..80fb191527 100644 --- a/src/dotnet/ShellShim/AppHostShimMaker.cs +++ b/src/dotnet/ShellShim/AppHostShimMaker.cs @@ -39,8 +39,8 @@ public void CreateApphostShellShim(FilePath entryPoint, FilePath shimPath) appHostSourcePath = Path.Combine(_appHostSourceDirectory, ApphostNameWithoutExtension); } - var appHostDestinationFilePath = shimPath.Value; - var appBinaryFilePath = PathUtility.GetRelativePath(appHostDestinationFilePath, entryPoint.Value); + var appHostDestinationFilePath = Path.GetFullPath(shimPath.Value); + var appBinaryFilePath = Path.GetRelativePath(Path.GetDirectoryName(appHostDestinationFilePath), Path.GetFullPath(entryPoint.Value)); EmbedAppNameInHost.EmbedAndReturnModifiedAppHostPath( appHostSourceFilePath: appHostSourcePath, diff --git a/test/Microsoft.DotNet.ShellShim.Tests/ShellShimRepositoryTests.cs b/test/Microsoft.DotNet.ShellShim.Tests/ShellShimRepositoryTests.cs index 90a3bb83dc..54b0266a3d 100644 --- a/test/Microsoft.DotNet.ShellShim.Tests/ShellShimRepositoryTests.cs +++ b/test/Microsoft.DotNet.ShellShim.Tests/ShellShimRepositoryTests.cs @@ -45,6 +45,27 @@ public void GivenAnExecutablePathItCanGenerateShimFile() stdOut.Should().Contain("Hello World"); } + // Reproduce https://github.com/dotnet/cli/issues/9319 + [Fact] + public void GivenAnExecutableAndRelativePathToShimPathItCanGenerateShimFile() + { + var outputDll = MakeHelloWorldExecutableDll("GivenAnExecutableAndRelativePath"); + // To reproduce the bug, dll need to be nested under the shim + var parentPathAsShimPath = outputDll.GetDirectoryPath().GetParentPath().GetParentPath().Value; + var relativePathToShim = Path.GetRelativePath( + Directory.GetCurrentDirectory(), + parentPathAsShimPath); + + ShellShimRepository shellShimRepository = ConfigBasicTestDependecyShellShimRepository(relativePathToShim); + var shellCommandName = nameof(ShellShimRepositoryTests) + Path.GetRandomFileName(); + + shellShimRepository.CreateShim(outputDll, shellCommandName); + + var stdOut = ExecuteInShell(shellCommandName, relativePathToShim); + + stdOut.Should().Contain("Hello World"); + } + private static ShellShimRepository ConfigBasicTestDependecyShellShimRepository(string pathToShim) { string stage2AppHostTemplateDirectory = GetAppHostTemplateFromStage2(); @@ -473,13 +494,19 @@ private static string GetAppHostTemplateFromStage2() return stage2AppHostTemplateDirectory; } - private static FilePath MakeHelloWorldExecutableDll() + private static FilePath MakeHelloWorldExecutableDll(string instanceName = null) { const string testAppName = "TestAppSimple"; const string emptySpaceToTestSpaceInPath = " "; const string directoryNamePostFix = "Test"; + + if (instanceName == null) + { + instanceName = testAppName + emptySpaceToTestSpaceInPath + directoryNamePostFix; + } + TestAssetInstance testInstance = TestAssets.Get(testAppName) - .CreateInstance(testAppName + emptySpaceToTestSpaceInPath + directoryNamePostFix) + .CreateInstance(instanceName) .UseCurrentRuntimeFrameworkVersion() .WithRestoreFiles() .WithBuildFiles();