From 26716512c1165d670d6c7ee42a18917cd5010553 Mon Sep 17 00:00:00 2001 From: ORelio Date: Sun, 11 Feb 2018 15:43:58 +0100 Subject: [PATCH] Fix Windows version detection for UTF-8 console Built-in Environment.OSVersion does not work on Win10. --- MinecraftClient/MinecraftClient.csproj | 3 +- MinecraftClient/Program.cs | 3 +- MinecraftClient/{ => WinAPI}/ConsoleIcon.cs | 2 +- MinecraftClient/WinAPI/WindowsVersion.cs | 95 +++++++++++++++++++++ 4 files changed, 100 insertions(+), 3 deletions(-) rename MinecraftClient/{ => WinAPI}/ConsoleIcon.cs (98%) create mode 100644 MinecraftClient/WinAPI/WindowsVersion.cs diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index 79a6c584..dc64c04b 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -96,7 +96,7 @@ - + @@ -235,6 +235,7 @@ + diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 30eded45..0706cff2 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Threading; using MinecraftClient.Protocol.Handlers.Forge; using MinecraftClient.Protocol.SessionCache; +using MinecraftClient.WinAPI; namespace MinecraftClient { @@ -49,7 +50,7 @@ namespace MinecraftClient } //Take advantage of Windows 10 / Mac / Linux UTF-8 console - if (Environment.Version.Major > 6 || isUsingMono) + if (isUsingMono || WindowsVersion.WinMajorVersion >= 10) { Console.OutputEncoding = Console.InputEncoding = Encoding.UTF8; } diff --git a/MinecraftClient/ConsoleIcon.cs b/MinecraftClient/WinAPI/ConsoleIcon.cs similarity index 98% rename from MinecraftClient/ConsoleIcon.cs rename to MinecraftClient/WinAPI/ConsoleIcon.cs index 30dc6460..a320580c 100644 --- a/MinecraftClient/ConsoleIcon.cs +++ b/MinecraftClient/WinAPI/ConsoleIcon.cs @@ -9,7 +9,7 @@ using System.IO; using System.Drawing; using System.Windows.Forms; -namespace MinecraftClient +namespace MinecraftClient.WinAPI { /// /// Allow to set the player skin as console icon, on Windows only. diff --git a/MinecraftClient/WinAPI/WindowsVersion.cs b/MinecraftClient/WinAPI/WindowsVersion.cs new file mode 100644 index 00000000..4a6c595c --- /dev/null +++ b/MinecraftClient/WinAPI/WindowsVersion.cs @@ -0,0 +1,95 @@ +using Microsoft.Win32; + +namespace MinecraftClient.WinAPI +{ + /// + /// Retrieve information about the current Windows version + /// + /// + /// Environment.OSVersion does not work with Windows 10. + /// It returns 6.2 which is Windows 8 + /// + /// + /// https://stackoverflow.com/a/37755503 + /// + class WindowsVersion + { + /// + /// Returns the Windows major version number for this computer. + /// + public static uint WinMajorVersion + { + get + { + dynamic major; + // The 'CurrentMajorVersionNumber' string value in the CurrentVersion key is new for Windows 10, + // and will most likely (hopefully) be there for some time before MS decides to change this - again... + if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", out major)) + { + return (uint) major; + } + + // When the 'CurrentMajorVersionNumber' value is not present we fallback to reading the previous key used for this: 'CurrentVersion' + dynamic version; + if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out version)) + return 0; + + var versionParts = ((string) version).Split('.'); + if (versionParts.Length != 2) return 0; + uint majorAsUInt; + return uint.TryParse(versionParts[0], out majorAsUInt) ? majorAsUInt : 0; + } + } + + /// + /// Returns the Windows minor version number for this computer. + /// + public static uint WinMinorVersion + { + get + { + dynamic minor; + // The 'CurrentMinorVersionNumber' string value in the CurrentVersion key is new for Windows 10, + // and will most likely (hopefully) be there for some time before MS decides to change this - again... + if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMinorVersionNumber", + out minor)) + { + return (uint) minor; + } + + // When the 'CurrentMinorVersionNumber' value is not present we fallback to reading the previous key used for this: 'CurrentVersion' + dynamic version; + if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out version)) + return 0; + + var versionParts = ((string) version).Split('.'); + if (versionParts.Length != 2) return 0; + uint minorAsUInt; + return uint.TryParse(versionParts[1], out minorAsUInt) ? minorAsUInt : 0; + } + } + + /// + /// Try retrieving a registry key + /// + /// key path + /// Key + /// Value (output) + /// TRUE if successfully retrieved + private static bool TryGetRegistryKey(string path, string key, out dynamic value) + { + value = null; + try + { + var rk = Registry.LocalMachine.OpenSubKey(path); + if (rk == null) return false; + value = rk.GetValue(key); + return value != null; + } + catch + { + return false; + } + } + } +}