diff --git a/src/Compilers/Core/MSBuildTaskTests/TestUtilities/TaskTestUtil.cs b/src/Compilers/Core/MSBuildTaskTests/TestUtilities/TaskTestUtil.cs index e804b44859081..80521b800d154 100644 --- a/src/Compilers/Core/MSBuildTaskTests/TestUtilities/TaskTestUtil.cs +++ b/src/Compilers/Core/MSBuildTaskTests/TestUtilities/TaskTestUtil.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -41,23 +40,7 @@ public static void AssertCommandLine( var message = engine.BuildMessages.OfType().Single(); var commandLine = message.CommandLine.Replace(" ", " ").Trim(); - - var dotnetPath = RuntimeHostInfo.GetDotNetPathOrDefault(); - var expectedCommandLine = $@"{dotnetPath} exec ""{task.PathToManagedTool}"" {line}"; - - bool isOnlyFileName = Path.GetFileName(dotnetPath).Length == dotnetPath.Length; - if (isOnlyFileName) - { - // When ToolTask.GenerateFullPathToTool() returns only a file name (not a path to a file), MSBuild's ToolTask - // will search the %PATH% (see https://github.com/dotnet/msbuild/blob/5410bf323451e04e99e79bcffd158e6d8d378149/src/Utilities/ToolTask.cs#L494-L513) - // and log the full path to the exe. In this case, only assert that the commandLine ends with the expected - // command line, and ignore the full path at the beginning. - Assert.EndsWith(expectedCommandLine, commandLine); - } - else - { - Assert.Equal(expectedCommandLine, commandLine); - } + Assert.Equal($@"{RuntimeHostInfo.GetDotNetPathOrDefault()} exec ""{task.PathToManagedTool}"" {line}", commandLine); compilerTask.NoConfig = true; Assert.Equal("/noconfig", compilerTask.GenerateToolArguments()); diff --git a/src/Compilers/Shared/RuntimeHostInfo.cs b/src/Compilers/Shared/RuntimeHostInfo.cs index 31589a5375cd2..0f08c684f7ef9 100644 --- a/src/Compilers/Shared/RuntimeHostInfo.cs +++ b/src/Compilers/Shared/RuntimeHostInfo.cs @@ -53,11 +53,40 @@ internal static (string processFilePath, string commandLineArguments, string too /// /// Get the path to the dotnet executable. In the case the .NET SDK did not provide this information - /// in the environment this will return simply "dotnet". + /// in the environment this tries to find "dotnet" on the PATH. In the case it is not found, + /// this will return simply "dotnet". /// - internal static string GetDotNetPathOrDefault() => - Environment.GetEnvironmentVariable(DotNetHostPathEnvironmentName) ?? - (PlatformInformation.IsWindows ? "dotnet.exe" : "dotnet"); + internal static string GetDotNetPathOrDefault() + { + if (Environment.GetEnvironmentVariable(DotNetHostPathEnvironmentName) is string pathToDotNet) + { + return pathToDotNet; + } + + var (fileName, sep) = PlatformInformation.IsWindows + ? ("dotnet.exe", ';') + : ("dotnet", ':'); + + var path = Environment.GetEnvironmentVariable("PATH") ?? ""; + foreach (var item in path.Split(sep, StringSplitOptions.RemoveEmptyEntries)) + { + try + { + var filePath = Path.Combine(item, fileName); + if (File.Exists(filePath)) + { + return filePath; + } + } + catch + { + // If we can't read a directory for any reason just skip it + } + } + + return fileName; + } + #else internal static bool IsCoreClrRuntime => false;