You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取Windows版本的正确方法:替代已弃用的GetVersionEx且兼容未来版本

获取Windows真实版本的可靠方法(替代已弃用的GetVersionEx)

嘿,我完全理解你的需求——要替代已弃用的GetVersionEx,拿到Windows的真实版本信息用来生成报告,而且得兼容Windows 11甚至未来的系统,毕竟GetVersionEx在新系统上会返回假数据,确实挺烦人的。下面这几个靠谱的方法,你可以根据自己的场景选:

方法一:使用RtlGetVersion函数

这个是Windows内核提供的函数,不会受到应用程序兼容性上下文的影响,能返回最原始的系统版本信息。它属于ntdll.dll,可以直接声明调用,也可以动态加载(更稳妥,避免编译依赖问题)。

C++代码示例

#include <windows.h>
#include <winternl.h>
#include <wchar.h>

#pragma comment(lib, "ntdll.lib")

// 动态加载的方式(可选,避免编译时依赖ntdll.lib)
typedef NTSTATUS(WINAPI* RtlGetVersionFunc)(PRTL_OSVERSIONINFOEXW);

BOOL GetRealWindowsVersion(OSVERSIONINFOEXW& osvi)
{
    ZeroMemory(&osvi, sizeof(osvi));
    osvi.dwOSVersionInfoSize = sizeof(osvi);

    // 获取RtlGetVersion函数地址
    HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
    if (!hNtdll) return FALSE;

    RtlGetVersionFunc pRtlGetVersion = (RtlGetVersionFunc)GetProcAddress(hNtdll, "RtlGetVersion");
    if (!pRtlGetVersion) return FALSE;

    NTSTATUS status = pRtlGetVersion(&osvi);
    return NT_SUCCESS(status);
}

// 使用示例
int main()
{
    OSVERSIONINFOEXW osvi;
    if (GetRealWindowsVersion(osvi))
    {
        wprintf(L"主版本号: %u\n", osvi.dwMajorVersion);
        wprintf(L"次版本号: %u\n", osvi.dwMinorVersion);
        wprintf(L"构建号: %u\n", osvi.dwBuildNumber);
        wprintf(L"产品类型: %u\n", osvi.wProductType);
        // 划重点:Windows 11的主版本是10,次版本0,构建号≥22000
    }
    return 0;
}

这个方法返回的结构和GetVersionEx几乎一致,能轻松拿到你需要的版本参数,未来Windows版本更新后,构建号会持续递增,通过构建号就能区分不同系统版本。

方法二:读取注册表项

这是最通用的方法,几乎所有编程语言都能实现,直接读取Windows系统维护的注册表项,完全不受兼容性设置干扰。需要访问的注册表路径是HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion,里面的关键值涵盖了所有你需要的报告信息:

  • ProductName:直接显示系统全称(比如“Windows 11 Pro”)
  • CurrentVersion:主版本号(Win10/Win11都是10.0)
  • CurrentBuildNumber:核心构建号(Win10是1904x系列,Win11是22000+)
  • UBR:更新构建版本(比如22621.1265中的1265)
  • ReleaseId:发布分支ID(比如Win11的22H2)

PowerShell示例(快速验证)

$regPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
$versionData = Get-ItemProperty -Path $regPath

Write-Host "系统名称: $($versionData.ProductName)"
Write-Host "完整版本: $($versionData.CurrentVersion).$($versionData.CurrentBuildNumber).$($versionData.UBR)"
Write-Host "发布分支: $($versionData.ReleaseId)"

C++代码示例

#include <windows.h>
#include <string>
#include <iostream>

std::wstring GetRegistryStringValue(HKEY rootKey, const wchar_t* subKey, const wchar_t* valueName)
{
    HKEY hSubKey;
    if (RegOpenKeyExW(rootKey, subKey, 0, KEY_READ | KEY_WOW64_64KEY, &hSubKey) != ERROR_SUCCESS)
        return L"";

    wchar_t buffer[512];
    DWORD bufferSize = sizeof(buffer);
    DWORD valueType;
    std::wstring result;

    if (RegQueryValueExW(hSubKey, valueName, nullptr, &valueType, (LPBYTE)buffer, &bufferSize) == ERROR_SUCCESS && valueType == REG_SZ)
    {
        result = buffer;
    }

    RegCloseKey(hSubKey);
    return result;
}

int main()
{
    std::wstring productName = GetRegistryStringValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"ProductName");
    std::wstring currentVersion = GetRegistryStringValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"CurrentVersion");
    std::wstring buildNumber = GetRegistryStringValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"CurrentBuildNumber");
    std::wstring ubr = GetRegistryStringValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"UBR");

    std::wcout << L"系统名称: " << productName << std::endl;
    std::wcout << L"完整版本号: " << currentVersion << L"." << buildNumber << L"." << ubr << std::endl;

    return 0;
}

注意:代码里加了KEY_WOW64_64KEY,是为了让32位程序也能读取64位注册表的真实值,避免拿到错误数据。

方法三:读取kernel32.dll的文件版本

系统核心文件kernel32.dll的文件版本就是Windows的真实版本,不会被兼容性策略篡改。可以用Windows的GetFileVersionInfo系列函数来获取。

C++代码示例

#include <windows.h>
#include <string>
#include <iostream>

std::wstring GetKernel32FileVersion()
{
    wchar_t systemDir[MAX_PATH];
    GetSystemDirectoryW(systemDir, MAX_PATH);
    wcscat_s(systemDir, L"\\kernel32.dll");

    DWORD dummy;
    DWORD versionInfoSize = GetFileVersionInfoSizeW(systemDir, &dummy);
    if (versionInfoSize == 0)
        return L"";

    std::vector<BYTE> versionBuffer(versionInfoSize);
    if (!GetFileVersionInfoW(systemDir, 0, versionInfoSize, versionBuffer.data()))
        return L"";

    VS_FIXEDFILEINFO* fileInfo = nullptr;
    UINT infoSize;
    if (!VerQueryValueW(versionBuffer.data(), L"\\", (LPVOID*)&fileInfo, &infoSize))
        return L"";

    std::wstring versionStr;
    versionStr += std::to_wstring(HIWORD(fileInfo->dwFileVersionMS)) + L".";
    versionStr += std::to_wstring(LOWORD(fileInfo->dwFileVersionMS)) + L".";
    versionStr += std::to_wstring(HIWORD(fileInfo->dwFileVersionLS)) + L".";
    versionStr += std::to_wstring(LOWORD(fileInfo->dwFileVersionLS));

    return versionStr;
}

int main()
{
    std::wstring winVersion = GetKernel32FileVersion();
    std::wcout << L"Windows真实版本: " << winVersion << std::endl;
    return 0;
}

这个方法获取到的版本号和系统设置里显示的完全一致,比如Win11 22H2会返回10.0.22621.1265这类完整版本字符串。


如果是生成报告,我个人推荐注册表方法,能直接拿到用户友好的系统名称和完整版本信息;如果是在程序里需要版本数值做逻辑处理,RtlGetVersion或者kernel32版本方法都很靠谱。这三个方法都能绕过兼容性限制,返回真实的系统版本,而且会一直兼容未来的Windows版本。

内容的提问来源于stack exchange,提问作者Jabberwocky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:19:25