mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-08-03 19:36:53 -04:00
创建 WindowsVersion 工具类 (#3932)
This commit is contained in:
parent
68c8a30bd7
commit
58a4700a46
@ -20,6 +20,8 @@ package org.jackhuang.hmcl.util.platform;
|
|||||||
import org.jackhuang.hmcl.util.KeyValuePairUtils;
|
import org.jackhuang.hmcl.util.KeyValuePairUtils;
|
||||||
import org.jackhuang.hmcl.util.platform.windows.Kernel32;
|
import org.jackhuang.hmcl.util.platform.windows.Kernel32;
|
||||||
import org.jackhuang.hmcl.util.platform.windows.WinTypes;
|
import org.jackhuang.hmcl.util.platform.windows.WinTypes;
|
||||||
|
import org.jackhuang.hmcl.util.platform.windows.WindowsVersion;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -106,6 +108,11 @@ public enum OperatingSystem {
|
|||||||
*/
|
*/
|
||||||
public static final int SYSTEM_BUILD_NUMBER;
|
public static final int SYSTEM_BUILD_NUMBER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version number is non-null if and only if the operating system is {@linkplain #WINDOWS}.
|
||||||
|
*/
|
||||||
|
public static final @Nullable WindowsVersion WINDOWS_VERSION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of current operating system.
|
* The name of current operating system.
|
||||||
*/
|
*/
|
||||||
@ -125,8 +132,6 @@ public enum OperatingSystem {
|
|||||||
private static final String[] INVALID_RESOURCE_BASENAMES;
|
private static final String[] INVALID_RESOURCE_BASENAMES;
|
||||||
private static final String[] INVALID_RESOURCE_FULLNAMES;
|
private static final String[] INVALID_RESOURCE_FULLNAMES;
|
||||||
|
|
||||||
private static final boolean IS_WINDOWS_7_OR_LATER;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String nativeEncoding = System.getProperty("native.encoding");
|
String nativeEncoding = System.getProperty("native.encoding");
|
||||||
String hmclNativeEncoding = System.getProperty("hmcl.native.encoding");
|
String hmclNativeEncoding = System.getProperty("hmcl.native.encoding");
|
||||||
@ -152,61 +157,35 @@ public enum OperatingSystem {
|
|||||||
NATIVE_CHARSET = nativeCharset;
|
NATIVE_CHARSET = nativeCharset;
|
||||||
|
|
||||||
if (CURRENT_OS == WINDOWS) {
|
if (CURRENT_OS == WINDOWS) {
|
||||||
String versionNumber = null;
|
|
||||||
int buildNumber = -1;
|
|
||||||
int codePage = -1;
|
int codePage = -1;
|
||||||
|
WindowsVersion windowsVersion = null;
|
||||||
|
|
||||||
Kernel32 kernel32 = Kernel32.INSTANCE;
|
Kernel32 kernel32 = Kernel32.INSTANCE;
|
||||||
|
|
||||||
// Get Windows version number
|
// Get Windows version number
|
||||||
if (kernel32 != null) {
|
if (kernel32 != null) {
|
||||||
WinTypes.OSVERSIONINFOEXW osVersionInfo = new WinTypes.OSVERSIONINFOEXW();
|
WinTypes.OSVERSIONINFOEXW osVersionInfo = new WinTypes.OSVERSIONINFOEXW();
|
||||||
if (kernel32.GetVersionExW(osVersionInfo)) {
|
if (kernel32.GetVersionExW(osVersionInfo)) {
|
||||||
int majorVersion = osVersionInfo.dwMajorVersion;
|
windowsVersion = new WindowsVersion(osVersionInfo.dwMajorVersion, osVersionInfo.dwMinorVersion, osVersionInfo.dwBuildNumber);
|
||||||
int minorVersion = osVersionInfo.dwMinorVersion;
|
|
||||||
|
|
||||||
buildNumber = osVersionInfo.dwBuildNumber;
|
|
||||||
versionNumber = majorVersion + "." + minorVersion + "." + buildNumber;
|
|
||||||
} else
|
} else
|
||||||
System.err.println("Failed to obtain OS version number (" + kernel32.GetLastError() + ")");
|
System.err.println("Failed to obtain OS version number (" + kernel32.GetLastError() + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (versionNumber == null) {
|
if (windowsVersion == null) {
|
||||||
try {
|
try {
|
||||||
Process process = Runtime.getRuntime().exec(new String[]{"cmd", "ver"});
|
Process process = Runtime.getRuntime().exec(new String[]{"cmd", "ver"});
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), NATIVE_CHARSET))) {
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), NATIVE_CHARSET))) {
|
||||||
Matcher matcher = Pattern.compile("(?<version>[0-9]+\\.[0-9]+\\.(?<build>[0-9]+)(\\.[0-9]+)?)]$")
|
Matcher matcher = Pattern.compile("(?<version>\\d+\\.\\d+\\.\\d+\\.\\d+?)]$")
|
||||||
.matcher(reader.readLine().trim());
|
.matcher(reader.readLine().trim());
|
||||||
|
if (matcher.find())
|
||||||
if (matcher.find()) {
|
windowsVersion = new WindowsVersion(matcher.group("version"));
|
||||||
versionNumber = matcher.group("version");
|
|
||||||
buildNumber = Integer.parseInt(matcher.group("build"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
process.destroy();
|
process.destroy();
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (versionNumber == null)
|
if (windowsVersion == null)
|
||||||
versionNumber = System.getProperty("os.version");
|
windowsVersion = new WindowsVersion(System.getProperty("os.version"));
|
||||||
|
|
||||||
int major;
|
|
||||||
int dotIndex = versionNumber.indexOf('.');
|
|
||||||
try {
|
|
||||||
if (dotIndex < 0)
|
|
||||||
major = Integer.parseInt(versionNumber);
|
|
||||||
else
|
|
||||||
major = Integer.parseInt(versionNumber.substring(0, dotIndex));
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
major = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Windows XP: NT 5.1~5.2
|
|
||||||
// Windows Vista: NT 6.0
|
|
||||||
// Windows 7: NT 6.1
|
|
||||||
|
|
||||||
IS_WINDOWS_7_OR_LATER = major >= 6 && !versionNumber.startsWith("6.0");
|
|
||||||
|
|
||||||
// Get Code Page
|
// Get Code Page
|
||||||
|
|
||||||
@ -219,9 +198,8 @@ public enum OperatingSystem {
|
|||||||
Matcher matcher = Pattern.compile("(?<cp>[0-9]+)$")
|
Matcher matcher = Pattern.compile("(?<cp>[0-9]+)$")
|
||||||
.matcher(reader.readLine().trim());
|
.matcher(reader.readLine().trim());
|
||||||
|
|
||||||
if (matcher.find()) {
|
if (matcher.find())
|
||||||
codePage = Integer.parseInt(matcher.group("cp"));
|
codePage = Integer.parseInt(matcher.group("cp"));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
process.destroy();
|
process.destroy();
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
@ -231,19 +209,20 @@ public enum OperatingSystem {
|
|||||||
String osName = System.getProperty("os.name");
|
String osName = System.getProperty("os.name");
|
||||||
|
|
||||||
// Java 17 or earlier recognizes Windows 11 as Windows 10
|
// Java 17 or earlier recognizes Windows 11 as Windows 10
|
||||||
if (osName.equals("Windows 10") && buildNumber >= 22000)
|
if (osName.equals("Windows 10") && windowsVersion.compareTo(WindowsVersion.WINDOWS_11) >= 0)
|
||||||
osName = "Windows 11";
|
osName = "Windows 11";
|
||||||
|
|
||||||
SYSTEM_NAME = osName;
|
SYSTEM_NAME = osName;
|
||||||
SYSTEM_VERSION = versionNumber;
|
SYSTEM_VERSION = windowsVersion.toString();
|
||||||
SYSTEM_BUILD_NUMBER = buildNumber;
|
SYSTEM_BUILD_NUMBER = windowsVersion.getBuild();
|
||||||
|
WINDOWS_VERSION = windowsVersion;
|
||||||
CODE_PAGE = codePage;
|
CODE_PAGE = codePage;
|
||||||
} else {
|
} else {
|
||||||
SYSTEM_NAME = System.getProperty("os.name");
|
SYSTEM_NAME = System.getProperty("os.name");
|
||||||
SYSTEM_VERSION = System.getProperty("os.version");
|
SYSTEM_VERSION = System.getProperty("os.version");
|
||||||
SYSTEM_BUILD_NUMBER = -1;
|
SYSTEM_BUILD_NUMBER = -1;
|
||||||
|
WINDOWS_VERSION = null;
|
||||||
CODE_PAGE = -1;
|
CODE_PAGE = -1;
|
||||||
IS_WINDOWS_7_OR_LATER = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> osRelease = Collections.emptyMap();
|
Map<String, String> osRelease = Collections.emptyMap();
|
||||||
@ -299,7 +278,7 @@ public enum OperatingSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isWindows7OrLater() {
|
public static boolean isWindows7OrLater() {
|
||||||
return IS_WINDOWS_7_OR_LATER;
|
return WINDOWS_VERSION != null && WINDOWS_VERSION.compareTo(WindowsVersion.WINDOWS_7) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Path getWorkingDirectory(String folder) {
|
public static Path getWorkingDirectory(String folder) {
|
||||||
|
@ -0,0 +1,143 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.util.platform.windows;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Glavo
|
||||||
|
* @see <a href="https://learn.microsoft.com/windows/win32/sysinfo/operating-system-version">Operating System Version</a>
|
||||||
|
*/
|
||||||
|
public final class WindowsVersion implements Comparable<WindowsVersion> {
|
||||||
|
|
||||||
|
public static final WindowsVersion UNKNOWN = new WindowsVersion(0, 0);
|
||||||
|
|
||||||
|
public static final WindowsVersion WINDOWS_2000 = new WindowsVersion(5, 0);
|
||||||
|
public static final WindowsVersion WINDOWS_XP = new WindowsVersion(5, 1);
|
||||||
|
public static final WindowsVersion WINDOWS_VISTA = new WindowsVersion(6, 0);
|
||||||
|
public static final WindowsVersion WINDOWS_7 = new WindowsVersion(6, 1);
|
||||||
|
public static final WindowsVersion WINDOWS_8 = new WindowsVersion(6, 2);
|
||||||
|
public static final WindowsVersion WINDOWS_8_1 = new WindowsVersion(6, 3);
|
||||||
|
public static final WindowsVersion WINDOWS_10 = new WindowsVersion(10, 0);
|
||||||
|
public static final WindowsVersion WINDOWS_11 = new WindowsVersion(10, 0, 22000);
|
||||||
|
|
||||||
|
private final int major;
|
||||||
|
private final int minor;
|
||||||
|
private final int build;
|
||||||
|
private final int revision;
|
||||||
|
private final String version;
|
||||||
|
|
||||||
|
public WindowsVersion(int major, int minor) {
|
||||||
|
this(major, minor, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WindowsVersion(int major, int minor, int build) {
|
||||||
|
this(major, minor, build, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WindowsVersion(int major, int minor, int build, int revision) {
|
||||||
|
this.major = major;
|
||||||
|
this.minor = minor;
|
||||||
|
this.build = build;
|
||||||
|
this.revision = revision;
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append(major).append('.').append(minor);
|
||||||
|
if (build > 0 || revision > 0) {
|
||||||
|
builder.append('.').append(build);
|
||||||
|
if (revision > 0) {
|
||||||
|
builder.append('.').append(revision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.version = builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WindowsVersion(@NotNull String version) {
|
||||||
|
this.version = Objects.requireNonNull(version);
|
||||||
|
|
||||||
|
Matcher matcher = Pattern.compile("^(?<major>\\d+)\\.(?<minor>\\d+)(\\.(?<build>\\d+)(\\.(?<revision>\\d+))?)?")
|
||||||
|
.matcher(version);
|
||||||
|
if (matcher.find()) {
|
||||||
|
this.major = Integer.parseInt(matcher.group("major"));
|
||||||
|
this.minor = Integer.parseInt(matcher.group("minor"));
|
||||||
|
this.build = matcher.group("build") != null ? Integer.parseInt(matcher.group("build")) : 0;
|
||||||
|
this.revision = matcher.group("revision") != null ? Integer.parseInt(matcher.group("revision")) : 0;
|
||||||
|
} else {
|
||||||
|
this.major = 0;
|
||||||
|
this.minor = 0;
|
||||||
|
this.build = 0;
|
||||||
|
this.revision = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMajor() {
|
||||||
|
return major;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinor() {
|
||||||
|
return minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBuild() {
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRevision() {
|
||||||
|
return revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull WindowsVersion that) {
|
||||||
|
if (this.major != that.major)
|
||||||
|
return Integer.compare(this.major, that.major);
|
||||||
|
if (this.minor != that.minor)
|
||||||
|
return Integer.compare(this.minor, that.minor);
|
||||||
|
if (this.build != that.build)
|
||||||
|
return Integer.compare(this.build, that.build);
|
||||||
|
return Integer.compare(this.revision, that.revision);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(major, minor, build, revision);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (!(o instanceof WindowsVersion))
|
||||||
|
return false;
|
||||||
|
WindowsVersion that = (WindowsVersion) o;
|
||||||
|
|
||||||
|
return this.major == that.major &&
|
||||||
|
this.minor == that.minor &&
|
||||||
|
this.build == that.build &&
|
||||||
|
this.revision == that.revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.util.platform.windows;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Glavo
|
||||||
|
*/
|
||||||
|
public final class WindowsVersionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse() {
|
||||||
|
assertEquals(WindowsVersion.WINDOWS_7, new WindowsVersion("6.1"));
|
||||||
|
assertEquals(WindowsVersion.WINDOWS_10, new WindowsVersion("10.0"));
|
||||||
|
assertEquals(new WindowsVersion(10, 0, 26120), new WindowsVersion("10.0.26120"));
|
||||||
|
assertEquals(new WindowsVersion(10, 0, 26120), new WindowsVersion("10.0.26120-unknown"));
|
||||||
|
assertEquals(new WindowsVersion(10, 0, 26120, 3964), new WindowsVersion("10.0.26120.3964"));
|
||||||
|
assertEquals(new WindowsVersion(10, 0, 26120, 3964), new WindowsVersion("10.0.26120.3964-unknown"));
|
||||||
|
|
||||||
|
assertEquals(WindowsVersion.UNKNOWN, new WindowsVersion("unknown"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user