Environment.OSVersion.Version 返回 10.0 是设计使然,因 Windows 10/11 内核同为 NT 10.0;可靠区分应查注册表 ReleaseId(如“23H2”为 Win11)或 CurrentMajorVersionNumber(Win11=4,Win10=3)。
Environment.OSVersion.Version 返回的永远是 10.0,不是 bug 是设计
windows 10 和 windows 11 的 environment.osversion.version 都返回 10.0.xxxx.xxxx,主次版本号完全一样——这不是 c# 的缺陷,而是微软从 windows 10 开始就明确弃用该字段做版本判别。系统内核未变(仍是 nt 10.0),所以 .net 直接透传了内核报告的版本号。
- 调用
Environment.OSVersion.Version.Major == 10 && Environment.OSVersion.Version.Minor == 0只能确认“是 Win10 或更新”,无法区分 Win10/Win11 -
Environment.OSVersion.Version.Build也靠不住:Win10 22H2 和 Win11 23H2 的构建号有重叠(如 22621 和 22631 都可能出现在两个系统中) - 不要试图靠
Revision或字符串解析VersionString来判断——它在不同 .NET 运行时下格式不一致,且 Win11 某些更新后会回退显示为 “10.0”
真正可靠的 Win10/Win11 区分法:查注册表 ReleaseId 或 CurrentMajorVersionNumber
微软官方推荐路径是读取注册表键 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion 下的 ReleaseId(字符串,如 "22H2"、"23H2")或 CurrentMajorVersionNumber(DWORD,Win11 为 4,Win10 为 3)。这是目前最稳定、无需额外权限、且被 Windows App SDK 和 WinUI 官方文档采纳的方式。
-
ReleaseId最直观:以"21H2"、"22H2"开头的是 Win10;"23H2"、"24H2"起始的是 Win11(注意:23H2 是首个正式版 Win11 版本号) -
CurrentMajorVersionNumber更底层:值为4表示 Win11,3表示 Win10(该值自 Win11 21H2 起引入,Win10 全系为 3) - 需引用
Microsoft.Win32.Registry,用Registry.GetValue()读取,避免打开句柄泄漏 - UWP / WinUI 3 应用需改用
Windows.System.Profile.AnalyticsInfo(但仅限已发布商店包,开发调试时不可靠)
WMI 查询 Win32_OperatingSystem:功能强但慢、有权限和兼容性风险
用 WMI 查询 Win32_OperatingSystem 类可拿到 ProductType、Version、BuildNumber 和 Caption(如 "Microsoft Windows 11 Pro"),看起来很全,但实际落地问题多。
- 首次查询极慢(可能 >500ms),因需启动 WMI 服务并加载提供程序
- 在沙盒环境(如某些企业终端管理策略)、最小化安装系统或容器中,WMI 可能被禁用或缺失
root\CIMV2命名空间 - .NET 6+ 在 Linux/macOS 上运行时,WMI 不可用,代码会抛
PlatformNotSupportedException - 若仅需区分 Win10/Win11,用 WMI 属于“杀鸡用牛刀”,且
Caption字符串本地化后内容不稳定(比如中文系统返回“Windows 11 专业版”)
WinRT API AnalyticsInfo.VersionInfo:UWP/WinUI 专属,但只在打包后生效
在 UWP 或 WinUI 3 应用中,Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily 返回 "Windows.Desktop",而 AnalyticsInfo.VersionInfo.OsBuildLabEx 可解析出类似 "22621.1.amd64fre.ni_release.220506-1250" 的字符串——但这个 API 有个致命限制:仅当应用以 MSIX 包形式安装并运行时才返回真实值;调试时(F5 直接运行)一律返回空或默认值。
- 开发阶段无法可靠测试,容易误判逻辑分支
- 不能用于后台任务或服务类进程(无 UI 线程上下文)
- 依赖
Windows.Foundation.UniversalApiContract,.NET Framework 项目无法使用 - 如果必须用,建议 fallback 到注册表方案,二者组合兜底
真正麻烦的不是“怎么写”,而是 Win11 故意模糊了版本边界——它不希望你硬编码判断。所以最稳妥的做法是:优先查注册表 ReleaseId,没读到再查 CurrentMajorVersionNumber,两者都失败才退到 Environment.OSVersion 做基础平台识别。别信字符串匹配,也别依赖构建号跨大版本比较。










