mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-20 01:46:13 +00:00
Implement better platform identification and descriptions in preloader log
This commit is contained in:
3 files changed
+162
-8
No files matched your search
@@ -31,6 +31,8 @@ internal static class NetPreloaderRunner
|
||||
|
||||
internal static void OuterMain(string[] args, string filename)
|
||||
{
|
||||
PlatformUtils.SetPlatform();
|
||||
|
||||
Paths.SetExecutablePath(filename);
|
||||
|
||||
AppDomain.CurrentDomain.AssemblyResolve += LocalResolve;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BepInEx.Logging;
|
||||
using BepInEx.Shared;
|
||||
using MonoMod.Utils;
|
||||
@@ -25,10 +27,120 @@ public static class ChainloaderLogHelper
|
||||
log.Log(LogLevel.Message, attribute.Info);
|
||||
}
|
||||
|
||||
Logger.Log(LogLevel.Info, $"System platform: {PlatformHelper.Current}");
|
||||
Logger.Log(LogLevel.Info, $"System platform: {GetPlatformString()}");
|
||||
Logger.Log(LogLevel.Info, $"Process bitness: {(PlatformUtils.ProcessIs64Bit ? "64-bit (x64)" : "32-bit (x86)")}");
|
||||
}
|
||||
|
||||
private static string GetPlatformString()
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
var osVersion = Environment.OSVersion.Version;
|
||||
|
||||
// NOTE: this logic needs to be different for .NET 5.
|
||||
// We don't use it and I don't think we will for a long time (possibly ever), but upgrading will break Environment.OSVersion
|
||||
// https://docs.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/5.0/environment-osversion-returns-correct-version#change-description
|
||||
|
||||
// Some additional notes
|
||||
// On .NET Framework and .NET Core platforms before 5, Environment.OSVersion does not work as you would expect.
|
||||
|
||||
// On Windows, it returns at maximum 6.3 (Windows 8) if you don't specify that your application is specifically compatible with Windows 10, due to compatibility layer stuff.
|
||||
// So we have to call RtlGetVersion which bypasses that and gets the values for us. This is done in PlatformUtils
|
||||
|
||||
// On macOS it returns the Darwin kernel version. I've included a mapping of most versions, but there's definitely some missing versions
|
||||
|
||||
// Not sure what it does on Linux. I think it returns the kernel version there too, but we already get the utsname structure from SetPlatform() regardless
|
||||
|
||||
if (PlatformHelper.Is(Platform.Windows))
|
||||
{
|
||||
osVersion = PlatformUtils.WindowsVersion;
|
||||
|
||||
builder.Append("Windows ");
|
||||
|
||||
// https://stackoverflow.com/a/2819962
|
||||
|
||||
if (osVersion.Major >= 10 && osVersion.Build >= 22000)
|
||||
builder.Append("11");
|
||||
else if (osVersion.Major >= 10)
|
||||
builder.Append("10");
|
||||
else if (osVersion.Major == 6 && osVersion.Minor == 3)
|
||||
builder.Append("8.1");
|
||||
else if (osVersion.Major == 6 && osVersion.Minor == 2)
|
||||
builder.Append("8");
|
||||
else if (osVersion.Major == 6 && osVersion.Minor == 1)
|
||||
builder.Append("7");
|
||||
else if (osVersion.Major == 6 && osVersion.Minor == 0)
|
||||
builder.Append("Vista");
|
||||
else if (osVersion.Major <= 5)
|
||||
builder.Append("XP");
|
||||
}
|
||||
else if (PlatformHelper.Is(Platform.MacOS))
|
||||
{
|
||||
builder.Append("macOS ");
|
||||
|
||||
|
||||
var osxVersion = osVersion.ToString(3);
|
||||
|
||||
if (MacOSVersions.TryGetValue(osxVersion, out var macOsVersion))
|
||||
{
|
||||
builder.Append(macOsVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendFormat("Unknown (kernel {0})", osVersion);
|
||||
}
|
||||
}
|
||||
else if (PlatformHelper.Is(Platform.Linux))
|
||||
{
|
||||
builder.Append("Linux");
|
||||
|
||||
if (PlatformUtils.LinuxKernelVersion != null)
|
||||
{
|
||||
builder.AppendFormat(" (kernel {0})", PlatformUtils.LinuxKernelVersion);
|
||||
}
|
||||
}
|
||||
|
||||
builder.Append(PlatformHelper.Is(Platform.Bits64) ? " 64-bit" : " 32-bit");
|
||||
|
||||
if (PlatformHelper.Is(Platform.Android))
|
||||
{
|
||||
builder.Append(" Android");
|
||||
}
|
||||
|
||||
if (PlatformHelper.Is(Platform.ARM))
|
||||
{
|
||||
builder.Append(" ARM");
|
||||
|
||||
if (PlatformHelper.Is(Platform.Bits64))
|
||||
builder.Append("64");
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> MacOSVersions { get; } = new()
|
||||
{
|
||||
// https://en.wikipedia.org/wiki/Darwin_%28operating_system%29#Release_history
|
||||
["16.0.0"] = "10.12",
|
||||
["16.5.0"] = "10.12.4",
|
||||
["16.6.0"] = "10.12.6",
|
||||
["17.5.0"] = "10.13.4",
|
||||
["17.6.0"] = "10.13.5",
|
||||
["17.7.0"] = "10.13.6",
|
||||
["18.2.0"] = "10.14.1",
|
||||
["19.2.0"] = "10.15.2",
|
||||
["19.3.0"] = "10.15.3",
|
||||
["19.5.0"] = "10.15.5.1",
|
||||
["20.1.0"] = "11.0",
|
||||
["20.2.0"] = "11.1",
|
||||
["20.3.0"] = "11.2",
|
||||
["20.4.0"] = "11.3",
|
||||
["20.5.0"] = "11.4",
|
||||
["21.0.1"] = "12.0",
|
||||
["21.1.0"] = "12.0.1",
|
||||
["21.2.0"] = "12.1",
|
||||
};
|
||||
|
||||
public static void RewritePreloaderLogs()
|
||||
{
|
||||
if (PreloaderConsoleListener.LogEvents == null || PreloaderConsoleListener.LogEvents.Count == 0)
|
||||
|
||||
@@ -16,7 +16,19 @@ internal static class PlatformUtils
|
||||
CharSet = CharSet.Ansi)]
|
||||
private static extern IntPtr uname_osx(ref utsname_osx utsname);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern bool RtlGetVersion(ref WindowsOSVersionInfoExW versionInfo);
|
||||
|
||||
|
||||
private static bool Is(this Platform current, Platform expected) => (current & expected) == expected;
|
||||
|
||||
|
||||
public static readonly bool ProcessIs64Bit = IntPtr.Size >= 8;
|
||||
public static Version WindowsVersion { get; set; }
|
||||
|
||||
public static string LinuxArchitecture { get; set; }
|
||||
public static string LinuxKernelVersion { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Recreation of MonoMod's PlatformHelper.DeterminePlatform method, but with libc calls instead of creating processes.
|
||||
@@ -40,13 +52,22 @@ internal static class PlatformUtils
|
||||
current = Platform.Windows;
|
||||
else if (platID.Contains("mac") || platID.Contains("osx"))
|
||||
current = Platform.MacOS;
|
||||
else if (platID.Contains("lin") || platID.Contains("unix")) current = Platform.Linux;
|
||||
else if (platID.Contains("lin") || platID.Contains("unix"))
|
||||
current = Platform.Linux;
|
||||
|
||||
if (Is(current, Platform.Linux) && Directory.Exists("/data") && File.Exists("/system/build.prop"))
|
||||
if (current.Is(Platform.Linux) && Directory.Exists("/data") && File.Exists("/system/build.prop"))
|
||||
current = Platform.Android;
|
||||
else if (Is(current, Platform.Unix) && Directory.Exists("/System/Library/AccessibilityBundles"))
|
||||
else if (current.Is(Platform.Unix) && Directory.Exists("/System/Library/AccessibilityBundles"))
|
||||
current = Platform.iOS;
|
||||
|
||||
if (current.Is(Platform.Windows))
|
||||
{
|
||||
var windowsVersionInfo = new WindowsOSVersionInfoExW();
|
||||
RtlGetVersion(ref windowsVersionInfo);
|
||||
|
||||
WindowsVersion = new Version((int)windowsVersionInfo.dwMajorVersion, (int)windowsVersionInfo.dwMinorVersion, 0, (int)windowsVersionInfo.dwBuildNumber);
|
||||
}
|
||||
|
||||
// Is64BitOperatingSystem has been added in .NET Framework 4.0
|
||||
var m_get_Is64BitOperatingSystem =
|
||||
typeof(Environment).GetProperty("Is64BitOperatingSystem")?.GetGetMethod();
|
||||
@@ -54,13 +75,13 @@ internal static class PlatformUtils
|
||||
current |= (bool) m_get_Is64BitOperatingSystem.Invoke(null, new object[0]) ? Platform.Bits64 : 0;
|
||||
else
|
||||
current |= IntPtr.Size >= 8 ? Platform.Bits64 : 0;
|
||||
|
||||
if ((Is(current, Platform.MacOS) || Is(current, Platform.Linux)) && Type.GetType("Mono.Runtime") != null)
|
||||
|
||||
if ((current.Is(Platform.MacOS) || current.Is(Platform.Linux)) && Type.GetType("Mono.Runtime") != null)
|
||||
{
|
||||
string arch;
|
||||
IntPtr result;
|
||||
|
||||
if (Is(current, Platform.MacOS))
|
||||
if (current.Is(Platform.MacOS))
|
||||
{
|
||||
var utsname_osx = new utsname_osx();
|
||||
result = uname_osx(ref utsname_osx);
|
||||
@@ -72,6 +93,9 @@ internal static class PlatformUtils
|
||||
var utsname_linux = new utsname_linux();
|
||||
result = uname_linux(ref utsname_linux);
|
||||
arch = utsname_linux.machine;
|
||||
|
||||
LinuxArchitecture = utsname_linux.machine;
|
||||
LinuxKernelVersion = utsname_linux.version;
|
||||
}
|
||||
|
||||
if (result == IntPtr.Zero && (arch.StartsWith("aarch") || arch.StartsWith("arm")))
|
||||
@@ -88,7 +112,23 @@ internal static class PlatformUtils
|
||||
PlatformHelper.Current = current;
|
||||
}
|
||||
|
||||
private static bool Is(Platform current, Platform expected) => (current & expected) == expected;
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
|
||||
public struct WindowsOSVersionInfoExW
|
||||
{
|
||||
private static uint size = (uint)Marshal.SizeOf(typeof(WindowsOSVersionInfoExW));
|
||||
public uint dwOSVersionInfoSize = size;
|
||||
public uint dwMajorVersion;
|
||||
public uint dwMinorVersion;
|
||||
public uint dwBuildNumber;
|
||||
public uint dwPlatformId;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string szCSDVersion;
|
||||
public ushort wServicePackMajor;
|
||||
public ushort wServicePackMinor;
|
||||
public ushort wSuiteMask;
|
||||
public byte wProductType;
|
||||
public byte wReserved;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct utsname_osx
|
||||
|
||||
Reference in new issue
Block a user