C#: Improve logic for looking up .NET runtime in standalone mode

Instead of only considering a fixed set of paths for `dotnet` and `mono`,
first attempt to lookup the paths based on the `PATH` environment variable.
This change also fixes a potential `System.IO.DirectoryNotFoundException` exception,
which could be thrown when the `shared/Microsoft.NETCore.App` folder was not
present.
This commit is contained in:
Tom Hvitved
2018-12-20 14:19:29 +01:00
parent 23a2bf1756
commit 9f375de716
2 changed files with 36 additions and 9 deletions

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using System.Linq;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.Standalone
{
@@ -20,11 +21,14 @@ namespace Semmle.Extraction.CSharp.Standalone
{
get
{
string[] dotnetDirs = { "/usr/share/dotnet", @"C:\Program Files\dotnet" };
var dotnetPath = FileUtils.FindExecutableOnPath("dotnet");
var dotnetDirs = dotnetPath != null
? new[] { dotnetPath }
: new[] { "/usr/share/dotnet", @"C:\Program Files\dotnet" };
var coreDirs = dotnetDirs.Select(d => Path.Combine(d, "shared", "Microsoft.NETCore.App"));
foreach (var dir in dotnetDirs.Where(Directory.Exists))
return Directory.EnumerateDirectories(Path.Combine(dir, "shared", "Microsoft.NETCore.App")).
OrderByDescending(d => Path.GetFileName(d));
foreach (var dir in coreDirs.Where(Directory.Exists))
return Directory.EnumerateDirectories(dir).OrderByDescending(Path.GetFileName);
return Enumerable.Empty<string>();
}
}
@@ -37,19 +41,22 @@ namespace Semmle.Extraction.CSharp.Standalone
{
get
{
string[] monoDirs = { "/usr/lib/mono", @"C:\Program Files\Mono\lib\mono" };
var monoPath = FileUtils.FindExecutableOnPath("mono");
var monoDirs = monoPath != null
? new[] { monoPath }
: new[] { "/usr/lib/mono", @"C:\Program Files\Mono\lib\mono" };
if (Directory.Exists(@"C:\Windows\Microsoft.NET\Framework64"))
{
return System.IO.Directory.EnumerateDirectories(@"C:\Windows\Microsoft.NET\Framework64", "v*").
OrderByDescending(d => Path.GetFileName(d));
return Directory.EnumerateDirectories(@"C:\Windows\Microsoft.NET\Framework64", "v*").
OrderByDescending(Path.GetFileName);
}
foreach (var dir in monoDirs.Where(Directory.Exists))
{
return System.IO.Directory.EnumerateDirectories(dir).
return Directory.EnumerateDirectories(dir).
Where(d => Char.IsDigit(Path.GetFileName(d)[0])).
OrderByDescending(d => Path.GetFileName(d));
OrderByDescending(Path.GetFileName);
}
return Enumerable.Empty<string>();

View File

@@ -1,4 +1,6 @@
using System;
using System.IO;
using System.Linq;
namespace Semmle.Util
{
@@ -50,5 +52,23 @@ namespace Semmle.Util
// Ignore
}
}
/// <summary>
/// Finds the path for the executable <paramref name="exe"/> based on the
/// <code>PATH</code> environment variable, and in the case of Windows the
/// <code>PATHEXT</code> environment variable.
///
/// Returns <code>null</code> of no path can be found.
/// </summary>
public static string FindExecutableOnPath(string exe)
{
var isWindows = Win32.IsWindows();
var paths = Environment.GetEnvironmentVariable("PATH").Split(isWindows ? ';' : ':');
var exes = isWindows
? Environment.GetEnvironmentVariable("PATHEXT").Split(';').Select(ext => exe + ext)
: new[] { exe };
var candidates = paths.Where(path => exes.Any(exe0 => File.Exists(Path.Combine(path, exe0))));
return candidates.FirstOrDefault();
}
}
}