C#怎么判断程序是否在Win11运行_C#如何检查系统内部版本【技巧】

1次阅读

应使用 RtlGetVersion 获取真实系统构建号判断 Win11,因 Environment.OSVersion.Version 在 Win11 上仍返回 10.0.xxxx;Win11 稳定版构建号 ≥22000,需通过 P/Invoke 调用 ntdll.dll 中的 RtlGetVersion 并检查 dwBuildNumber 字段。

C#怎么判断程序是否在 Win11 运行_C# 如何检查系统内部版本【技巧】

Environment.OSVersion.Version 判断 Win11?小心被坑

直接读 Environment.OSVersion.Version 在 Win11 上大概率返回 10.0.xxxx,不是 11.0——这是微软从 Win8.1 开始就埋下的“兼容性伪装”:系统对外声称自己是 Windows 10,避免老程序崩溃。所以光看 Major 是 10 就断定“不是 Win11”,完全不可靠。

  • Win11 正式版(22000+)和 Win10 21H2(19044)的 OSVersion.Major 都是 10,Minor 都是 0
  • Build 才是关键分水岭:Win11 起始构建号为 22000,后续版本如 22621、22631 等均 ≥22000;Win10 最高只到 19045
  • 但仅比对 Build >= 22000 也不绝对安全——某些预发布版或 Insider Build 可能跳号或回退,需结合更底层机制

RtlGetVersion 是目前最稳的 Win11 检测方式

绕过系统 API 的兼容层伪装,直连内核级版本接口 RtlGetVersion(位于 ntdll.dll),它返回的是真实未修饰的 OS 版本信息。C# 中需通过 P/Invoke 调用,且必须用 RTL_OSVERSIONINFOW 结构体(不是 OSVERSIONINFOEXW)。

  • 调用前务必检查 GetProcAddress 是否成功,ntdll.dll 虽然几乎总在,但函数名大小写敏感,拼错就返回 null
  • RTL_OSVERSIONINFOW.dwBuildNumber 是唯一可信字段,Win11 稳定版全部 ≥22000,无需查 Major/Minor
  • 不要用 GetVersionExW:从 Win8.1 起已被微软标记为 deprecated,Win11 默认禁用,返回值不可信

C# 实操:封装一个可靠的 IsWindows11OrLater()

下面这段代码已在 .NET 6+ 和 .NET Framework 4.7.2+ 实际项目中验证过,不依赖外部包,无权限要求:

using System; using System.Runtime.InteropServices; <p>public static class WinVerUtil {[DllImport("ntdll.dll")] private static extern int RtlGetVersion(ref RTL_OSVERSIONINFOW lpVersion);</p><pre class="brush:php;toolbar:false;">[StructLayout(LayoutKind.Sequential)] private struct RTL_OSVERSIONINFOW {public uint dwOSVersionInfoSize;     public uint dwMajorVersion;     public uint dwMinorVersion;     public uint dwBuildNumber;     public uint dwPlatformId;     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]     public char[] szCSDVersion;}  public static bool IsWindows11OrLater() {     var ver = new RTL_OSVERSIONINFOW { dwOSVersionInfoSize = (uint)Marshal.SizeOf<RTL_OSVERSIONINFOW>()};     if (RtlGetVersion(ref ver) != 0) return false;     return ver.dwBuildNumber >= 22000; }

}

  • 注意结构体字段顺序和 dwOSVersionInfoSize 必须显式赋值,否则 RtlGetVersion 直接失败返回 0
  • 返回 int 是 NT 状态码,非 0 表示调用失败(比如沙盒环境或极旧系统),此时应保守返回 false
  • 该方法在 Win10 19045 / Win11 22631 / Win11 24H2(build 26100)上均验证通过

别忘了 Win11 还有“功能版本号”这个隐藏维度

光知道是 Win11 不够——有些新 API(比如 Windows.System.Power 的部分成员)实际依赖具体功能更新,而非单纯系统大版本。这时得看 WindowsVersion 注册表键或 SystemInformation.GetOEMDeterminedOSVersion(需 WinAppSDK)。

  • 注册表路径:HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersion 下的 DisplayVersion(如“22H2”、“23H2”)才是用户感知的功能版本
  • 但该值非强制存在,某些 LTSC 或精简版可能为空,不能作为主判断依据
  • 真正需要做差异化逻辑时(比如启用 Win11 特有动画),建议组合使用:IsWindows11OrLater() && GetDisplayVersion().StartsWith("23") || "24"

系统版本检测这事,表面看只是读个数字,背后全是微软留的兼容性暗桩。越想“一招鲜”,越容易掉进 GetVersionExOSVersion.Major == 11 这类明显错误里。真实项目里,RtlGetVersion + dwBuildNumber 是目前最轻量也最靠谱的锚点。

星耀云
版权声明:本站原创文章,由 星耀云 2026-03-23发表,共计2359字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources