C语言如何获取OSVersionInfo系统版本信息?

99ANYc3cd6
预计阅读时长 22 分钟
位置: 首页 C语言 正文

在 Windows 平台下,获取操作系统版本信息最标准、最推荐的方法是使用 Windows API (Application Programming Interface),这个 API 专门为此目的设计,并且能正确处理从 Windows XP 到最新 Windows 11 的各种版本。

c语言 osversioninfo
(图片来源网络,侵删)

我们将重点介绍两种主要方法:

  1. 推荐方法 (现代 Windows 10/11): 使用 VerifyVersionInfoW 函数,这是微软官方推荐的方式。
  2. 传统方法 (兼容性更好): 使用 GetVersionEx 函数,虽然已部分废弃,但在旧系统上更简单直接。

使用 VerifyVersionInfoW (推荐)

这是获取操作系统版本信息的现代、正确的方法,它使用一个掩码来精确查询你关心的版本特性,而不是返回一个可能被误导的版本号。

关键函数和数据结构

  1. OSVERSIONINFOEXW 结构体:

    • 这是 OSVERSIONINFO 的扩展版本,包含了更丰富的信息,如服务包号、产品类型等。
    • wServicePackMajorwServicePackMinor: 主次服务包版本号。
    • dwMajorVersion: 主版本号 (Windows 10 是 10)。
    • dwMinorVersion: 次版本号 (Windows 10 的 21H2 更新是 0)。
    • dwBuildNumber: 内部构建号 (19044)。
    • dwPlatformId: 平台 ID (VER_PLATFORM_WIN32_NT 表示 Windows NT 及以后系统)。
  2. VerifyVersionInfoW 函数:

    c语言 osversioninfo
    (图片来源网络,侵删)
    • 作用: 检查当前系统是否满足指定的版本条件。
    • 优点: 可以精确查询,避免 GetVersion 的“兼容性模式”问题。
    • 参数:
      • lpVersionInformation: 指向 OSVERSIONINFOEXW 结构体的指针。
      • dwType: 一个掩码,指定要检查哪些版本信息 (VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER)。
      • dwlConditionMask: 一个条件掩码,定义了版本号的比较逻辑 (是否大于、等于某个版本)。

完整示例代码

这个示例将检查当前系统是否为 Windows 10 或更高版本。

#include <windows.h>
#include <stdio.h>
#include <tchar.h> // 为了 _tprintf
// 需要链接 Version.lib 库
// 在 Visual Studio 中,项目属性 -> 链接器 -> 输入 -> 附加依赖项 中添加 Version.lib
// 在 GCC/MinGW 中,使用 -lversion 参数
int main() {
    OSVERSIONINFOEXW osvi = { 0 };
    DWORDLONG dwlConditionMask = 0;
    int op = VER_GREATER_EQUAL; // 定义比较操作符: 大于或等于
    // 1. 初始化 OSVERSIONINFOEXW 结构体
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
    osvi.dwMajorVersion = 10; // 我们想检查的版本号: Windows 10
    osvi.dwMinorVersion = 0;
    // 2. 设置比较条件掩码
    // VER_SET_CONDITION 是一个宏,用于构建条件掩码
    VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op);
    VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op);
    // 3. 调用 VerifyVersionInfoW
    // 如果系统版本 >= Windows 10,则返回 TRUE
    if (VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask)) {
        _tprintf(_T("当前系统是 Windows 10 或更高版本,\n"));
        // 获取更详细的版本信息
        OSVERSIONINFOEXW detailed_osvi = { 0 };
        detailed_osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
        GetVersionExW((OSVERSIONINFOW*)&detailed_osvi);
        _tprintf(_T("主版本号: %d\n"), detailed_osvi.dwMajorVersion);
        _tprintf(_T("次版本号: %d\n"), detailed_osvi.dwMinorVersion);
        _tprintf(_T("构建号: %d\n"), detailed_osvi.dwBuildNumber);
        _tprintf(_T("服务包: %d.%d\n"), detailed_osvi.wServicePackMajor, detailed_osvi.wServicePackMinor);
        // 根据构建号判断具体是哪个 Windows 10/11 版本
        if (detailed_osvi.dwMajorVersion == 10) {
            if (detailed_osvi.dwBuildNumber >= 22000) {
                _tprintf(_T("具体版本: Windows 11\n"));
            } else {
                _tprintf(_T("具体版本: Windows 10\n"));
            }
        }
    } else {
        // 如果失败,调用 GetLastError 获取错误码
        DWORD dwError = GetLastError();
        if (dwError == ERROR_OLD_WIN_VERSION) {
            _tprintf(_T("当前系统是 Windows 10 以下的版本,\n"));
        } else {
            _tprintf(_T("调用 VerifyVersionInfo 失败,错误码: %d\n"), dwError);
        }
    }
    return 0;
}

如何编译

  • Visual Studio: 创建一个“控制台应用”项目,代码可以直接运行。
  • GCC/MinGW (命令行):
    gcc -o get_version get_version.c -lversion
    ./get_version

    注意: -lversion 链接 Version.lib 库是必须的。


使用 GetVersionEx (传统方法)

这个方法在旧的代码中很常见,但已从 Windows 8.1 和 Windows Server 2012 R2 起被弃用,在 Windows 8.1 及更高版本上,它为了兼容旧应用程序而返回一个被“伪装”过的版本号(即 Windows 8 的版本号)。不推荐在新项目中使用,除非你需要兼容非常古老的系统(如 Windows XP)。

完整示例代码

#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "version.lib") // 链接库
int main() {
    OSVERSIONINFO osvi = { 0 };
    // 1. 初始化结构体
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    // 2. 调用 GetVersionEx
    if (GetVersionEx(&osvi)) {
        printf("成功获取版本信息,\n");
        printf("主版本号: %d\n", osvi.dwMajorVersion);
        printf("次版本号: %d\n", osvi.dwMinorVersion);
        printf("构建号: %d\n", osvi.dwBuildNumber);
        printf("平台 ID: %d\n", osvi.dwPlatformId);
        printf("版本字符串: %s\n", osvi.szCSDVersion); // "Service Pack 3"
        // 简单判断
        if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
            printf("当前系统是 Windows NT 内核系统,\n");
            if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) {
                printf("具体版本: Windows 7\n");
            } else if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) {
                printf("具体版本: Windows 8\n"); // 在 Win10/11 上这里也会显示 Win8
            } else if (osvi.dwMajorVersion == 10) {
                // 在 Win10/11 上,这里的主版本号会是 10,但次版本号会是 0
                printf("主版本号是 10,但可能是 Windows 10/11 (GetVersionEx 不可靠),\n");
            }
        } else {
            printf("当前系统可能是 Windows 95/98/Me,\n");
        }
    } else {
        printf("调用 GetVersionEx 失败,错误码: %d\n", GetLastError());
    }
    return 0;
}

总结与对比

特性 VerifyVersionInfoW (推荐) GetVersionEx (传统)
推荐度 低 (已弃用)
可靠性 ,不受应用程序兼容性模式影响 ,在 Win8.1+ 上返回被伪装的版本号
灵活性 ,可以精确查询特定版本条件 ,只能获取完整信息,无法进行精确查询
适用系统 Windows XP 及以后 Windows XP 及以后 (但在新系统上信息不准)
使用场景 新项目,需要准确判断系统版本以调用特定 API 维护旧代码,或需要兼容 Windows XP 等非常古老的系统

跨平台考虑

如果你写的 C 代码需要在 Linux 或 macOS 上运行,那么上述 Windows API 是无效的,你需要使用各自平台的系统调用:

c语言 osversioninfo
(图片来源网络,侵删)
  • Linux: 解析 /proc/version 文件或使用 uname 系统调用。
    #include <sys/utsname.h>
    // ...
    struct utsname name;
    uname(&name);
    printf("OS: %s, Release: %s\n", name.sysname, name.release);
  • macOS: 同样使用 uname 系统调用,或者通过读取系统文件(如 /System/Library/CoreServices/SystemVersion.plist)来获取更详细的 macOS 版本。

在 Windows 平台下进行 C 语言编程时,若需获取操作系统版本信息,请务必使用 VerifyVersionInfoW 函数,这是微软官方推荐的最佳实践,能确保你的程序在各种 Windows 版本上都能正确、可靠地运行。

-- 展开阅读全文 --
头像
0dede.com是什么网站?
« 上一篇 2025-12-10
织梦channel typeid如何实现分类内容调用?
下一篇 » 2025-12-10

相关文章

取消
微信二维码
支付宝二维码

目录[+]