using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using System.Linq;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.Standalone
{
///
/// Locates .NET Runtimes.
///
internal static class Runtime
{
private static string ExecutingRuntime => RuntimeEnvironment.GetRuntimeDirectory();
///
/// Locates .NET Core Runtimes.
///
private static IEnumerable CoreRuntimes
{
get
{
var dotnetPath = FileUtils.FindProgramOnPath(Win32.IsWindows() ? "dotnet.exe" : "dotnet");
var dotnetDirs = dotnetPath is not null
? new[] { dotnetPath }
: new[] { "/usr/share/dotnet", @"C:\Program Files\dotnet" };
var coreDirs = dotnetDirs.Select(d => Path.Combine(d, "shared", "Microsoft.NETCore.App"));
var dir = coreDirs.FirstOrDefault(Directory.Exists);
if (dir is not null)
{
return Directory.EnumerateDirectories(dir).OrderByDescending(Path.GetFileName);
}
return Enumerable.Empty();
}
}
///
/// Locates .NET Desktop Runtimes.
/// This includes Mono and Microsoft.NET.
///
private static IEnumerable DesktopRuntimes
{
get
{
var monoPath = FileUtils.FindProgramOnPath(Win32.IsWindows() ? "mono.exe" : "mono");
var monoDirs = monoPath is not null
? new[] { monoPath }
: new[] { "/usr/lib/mono", @"C:\Program Files\Mono\lib\mono" };
if (Directory.Exists(@"C:\Windows\Microsoft.NET\Framework64"))
{
return Directory.EnumerateDirectories(@"C:\Windows\Microsoft.NET\Framework64", "v*")
.OrderByDescending(Path.GetFileName);
}
var dir = monoDirs.FirstOrDefault(Directory.Exists);
if (dir is not null)
{
return Directory.EnumerateDirectories(dir)
.Where(d => Char.IsDigit(Path.GetFileName(d)[0]))
.OrderByDescending(Path.GetFileName);
}
return Enumerable.Empty();
}
}
///
/// Gets the .NET runtime location to use for extraction
///
public static string GetRuntime(bool useSelfContained) => useSelfContained ? ExecutingRuntime : Runtimes.First();
private static IEnumerable Runtimes
{
get
{
foreach (var r in CoreRuntimes)
yield return r;
foreach (var r in DesktopRuntimes)
yield return r;
// A bad choice if it's the self-contained runtime distributed in codeql dist.
yield return ExecutingRuntime;
}
}
}
}