C++如何获取Windows系统版本号_C++调用VerifyVersionInfo接口【系统】

4次阅读

VerifyVersionInfoW 优于 VerifyVersionInfoA,因后者受 ANSI 编码和区域设置影响;但二者均需配合 VerSetConditionMask 且受 manifest 限制,推荐优先使用不受限的 RtlGetVersion 获取真实系统版本。

C++如何获取Windows系统版本号_C++调用VerifyVersionInfo接口【系统】

VerifyVersionInfoA 和 VerifyVersionInfoW 的区别与选择

windows 提供的 VerifyVersionInfoAVerifyVersionInfoW 是同一 API 的 ANSI/Unicode 版本,但实际使用中几乎没人直接调用它们——因为从 windows 8.1 开始,微软明确要求必须配合 VerSetConditionMask 使用,且 OSVERSIONINFOEX 结构体字段需严格初始化,否则返回 FALSE 即使系统满足条件。

更关键的是:自 Windows 10 1607 起,VerifyVersionInfo 在应用未声明兼容性时会被系统静默降级为 Windows 8.1 版本号(即返回 dwMajorVersion=6, dwMinorVersion=3),哪怕你真在 win11 上跑。

  • 必须在 manifest 中声明支持目标系统,例如添加 win10)或对应 Win11 GuiD
  • dwOSVersionInfoSize 字段必须设为 sizeof(OSVERSIONINFOEX),漏设会导致调用失败
  • 推荐优先用 VerifyVersionInfoW,避免 ANSI 编码路径下区域设置引发的不可靠比较

比 VerifyVersionInfo 更可靠的做法:RtlGetVersion

RtlGetVersion 是内核导出函数,不走 UAC 兼容层,也不受 manifest 限制,返回真实内核版本。它在 ntdll.dll 中,无需 manifest 声明,且从 Windows XP 到 windows 11 全系可用。

注意它不是公开 Win32 API,头文件不声明,需手动 GetProcaddress 获取函数指针

立即学习C++免费学习笔记(深入)”;

typedef NTSTATUS(NTAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); HMODULE hNtDll = GetModuleHandleA("ntdll.dll"); RtlGetVersionPtr pRtlGetVersion = (RtlGetVersionPtr)GetProcAddress(hNtDll, "RtlGetVersion"); RTL_OSVERSIONINFOW osvi = {0}; osvi.dwOSVersionInfoSize = sizeof(osvi); if (pRtlGetVersion && pRtlGetVersion(&osvi) == 0) {     // osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildnumber 可信 }
  • 返回值为 NTSTATUS,成功是 0STATUS_SUCCESS),不是布尔值
  • RTL_OSVERSIONINFOWOSVERSIONINFOW 字段布局一致,但前者是 ntdll 内部结构,不能混用 typedef
  • 不需要 #include 或链接 ntdll.lib,纯运行时绑定即可

获取带具体版本名(如 “Windows 11”)的字符串

RtlGetVersion 只给数字版号,要转成用户可读名称,得查表匹配:dwMajorVersion + dwMinorVersion + dwBuildNumber 组合决定具体 SKU。

例如:

  • 10.0.22621 → Windows 11 22H2
  • 10.0.19045 → Windows 10 22H2
  • 6.3.9600 → Windows 8.1

微软未提供官方字符串映射 API,GetProductInfo 只能返回 PRODUCT_PROFESSIONAL 这类枚举,不带年份/代号。所以实际项目中建议维护一个轻量静态表,按 dwBuildNumber 区间判断(比只看主次版本更准):

if (osvi.dwMajorVersion == 10 && osvi.dwBuildNumber >= 22000) {     return "Windows 11"; } else if (osvi.dwMajorVersion == 10) {     return "Windows 10"; } else if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3) {     return "Windows 8.1"; }

Build number 是唯一稳定标识,比如 10.0.1904110.0.19045 都是 Win10 2004/20H2,但后者是累积更新版本——用 Build 判断兼容性比拼凑字符串靠谱得多。

VerifyVersionInfo 失败的典型错误现象

直接调用 VerifyVersionInfo 返回 FALSE 却没报错,是最常见的迷雾现场。常见原因包括:

  • VerSetConditionMask 返回值未用于 dwTypeMask,导致传入 0 —— 系统认为“不关心任何条件”,直接拒绝
  • OSVERSIONINFOEX 中未初始化所有字段(尤其是 wServicePackMajorwSuiteMask),未设的字段是垃圾值,比较必然失败
  • 忘记调用 ZeroMemory(&osvi, sizeof(osvi))dwOSVersionInfoSize 字段残留随机值
  • 在非 UI 线程(如 DLL_PROCESS_ATTACH)中首次调用,触发内部 GDI 初始化失败,间接导致验证失败

这些细节一旦漏掉,VerifyVersionInfo 就像个哑巴函数,既不崩溃也不报错,只默默返回 FALSE。调试时务必检查 GetLastError(),它通常会返回 ERROR_OLD_WIN_VERSIONERROR_INVALID_PARAMETER

text=ZqhQzanResources