检测Windows 11: .NET Framework 与 Windows API 方法
2025-01-21 01:04:59
检测 Windows 11:.NET Framework 和 Windows API 方法
识别运行中的 Windows 系统版本,对于应用兼容性处理至关重要。 本文介绍如何通过 .NET Framework 和 Windows API 检测 Windows 11 系统,并解释其中的原理。
.NET Framework 的检测方法
.NET Framework
的 System.Environment.OSVersion
属性可以提供操作系统的主要版本号和次要版本号,在大部分情况下能够识别 Windows 系统。 对于Windows 10 及其之前版本,其 Major
和 Minor
属性的值足以判断。但该方法对 Windows 11 有其局限性。 Windows 11 返回的系统版本号依然是10.0,和 Windows 10 相同,这导致我们不能直接用它区分 Windows 10 与 Windows 11。
利用 Windows.Management.OperatingSystem
类
一个更可靠的方式是通过使用 Windows.Management
命名空间中的 OperatingSystem
类。这个类属于 Windows Runtime API 的一部分,为更细致的操作系统信息提供了支持,并可区分 Windows 10 和 Windows 11。 它提供了一个更为清晰、直接的方式。
操作步骤:
- 添加对
Windows.winmd
的引用:需要手动添加到项目中,此文件通常在%ProgramFiles(x86)%\Windows Kits\10\UnionMetadata\windows.winmd
。 - 编写代码使用
Windows.Management.OperatingSystem.Version
获取详细版本信息,使用Build
属性即可判断系统版本,比如 22000以上就是Windows 11.using System; using System.Reflection; using System.Runtime.InteropServices; public class OsVersionDetector { public static void GetVersion() { try { var operatingSystemType = Type.GetTypeFromProgID("Windows.Management.OperatingSystem"); if (operatingSystemType != null) { var operatingSystemInstance = Activator.CreateInstance(operatingSystemType); var versionProperty = operatingSystemType.GetProperty("Version"); if (versionProperty!= null) { var versionObject = versionProperty.GetValue(operatingSystemInstance,null); if (versionObject!= null) { var versionType = versionObject.GetType(); var buildProperty = versionType.GetProperty("Build"); if(buildProperty!= null) { var build = (int)buildProperty.GetValue(versionObject, null); Console.WriteLine("Build number: "+build.ToString()); if (build >= 22000) { Console.WriteLine("Windows 11 Detected."); } else { Console.WriteLine("Not Windows 11, might be an older Windows Version."); } } else { Console.WriteLine("Error: Could not find build number"); } } else { Console.WriteLine("Error: Could not find operating system version info."); } }else{ Console.WriteLine("Error: Can not get Windows Runtime API for version number detection"); } } catch(Exception ex) { Console.WriteLine("Error in accessing system runtime api for version: "+ ex.Message ); } } }
这个方法无需考虑系统的具体版本号,只需检查`Build` 属性。这种方式相对可靠,并能够适应 Windows 版本更新。
## Windows API 的检测方法
Windows API 提供了一系列函数,帮助开发者获取操作系统信息。`GetVersion` 函数已被弃用, 不应再使用。 但可以利用`RtlGetVersion` API函数替代获取更详细版本信息。
### 利用 `RtlGetVersion`
`RtlGetVersion` API函数返回的是 `RTL_OSVERSIONINFOEX` 结构体。 这是一个内部未导出函数, 故而需要通过动态获取函数地址使用。 `RTL_OSVERSIONINFOEX` 中提供了包括 `MajorVersion`, `MinorVersion` 和 `BuildNumber` 等详细版本信息。
操作步骤:
1. 声明需要的结构体和函数原型:首先,需要在代码中声明 `RTL_OSVERSIONINFOEX` 结构体和 `RtlGetVersion` 函数原型。
```csharp
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct RTL_OSVERSIONINFOEX
{
internal uint dwOSVersionInfoSize;
internal uint dwMajorVersion;
internal uint dwMinorVersion;
internal uint dwBuildNumber;
internal uint dwPlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
internal string szCSDVersion;
internal ushort wServicePackMajor;
internal ushort wServicePackMinor;
internal ushort wSuiteMask;
internal byte wProductType;
internal byte wReserved;
}
[DllImport("ntdll.dll")]
internal static extern int RtlGetVersion(out RTL_OSVERSIONINFOEX lpVersionInformation);
```
2. 调用 `RtlGetVersion` API 并分析版本信息:获取到 `RTL_OSVERSIONINFOEX` 结构体后,可以分析其内部字段,特别关注 `dwMajorVersion`, `dwMinorVersion`, `dwBuildNumber` 。如果 `dwMajorVersion` 是 10, 且 `dwBuildNumber` 大于等于 22000,则判断为 Windows 11。
```csharp
public static void GetVersionFromAPI() {
RTL_OSVERSIONINFOEX osVersionInfo = new RTL_OSVERSIONINFOEX();
osVersionInfo.dwOSVersionInfoSize = (uint)Marshal.SizeOf(osVersionInfo);
int result = RtlGetVersion(out osVersionInfo);
if (result >= 0)
{
Console.WriteLine($"Windows Version {osVersionInfo.dwMajorVersion}.{osVersionInfo.dwMinorVersion}.{osVersionInfo.dwBuildNumber}");
if (osVersionInfo.dwMajorVersion == 10 && osVersionInfo.dwBuildNumber >= 22000)
{
Console.WriteLine("Detected: Windows 11");
}else
{
Console.WriteLine("Not Windows 11, maybe Windows 10 or less");
}
} else
{
Console.WriteLine("Error getting OS version with win32 api RtlGetVersion()");
}
}
这个方法可以直接读取操作系统版本信息,对需要兼容较旧系统应用场景很适用,提供了底层操作系统的控制能力。 同时, 由于该方法调用了系统内部API, 务必保证有足够的操作权限,并谨慎处理版本差异情况。
额外建议
使用上述方式识别系统版本后,不要盲目基于操作系统版本号硬编码处理逻辑。尽可能采用特性检测或运行时的条件检查。这能使你的应用程序更加健壮。
在开发过程中,应仔细考虑版本兼容性,尤其是对那些涉及到操作系统底层特性的应用。做好错误处理并准备适当的回退策略是最佳实践。 在Windows 11 发布后,需要及时更新相关的测试和代码来确保其能识别 Windows 11 系统。