原文:http://www.cnblogs.com/VOIP/archive/2011/03/22/1990927.html

Windows API 中有两个函数可以得到系统版本信息GetVersionGetVersionEx

GetVersion这个函数曾经困扰了很多程序员,其本来设计的是在DWORD返回值中用低位的那个字表示MS-DOS的版本号,高位的那个字表示Windows版本号。对于每个字来说,高位字节代表主要版本号,低位字节代表次要版本号。可是因为编写此函数的程序员犯了一个错误,使得此函数返回的Windows版本号颠倒了(即把主要版本号放到了低位字节,而次要版本号放到了高位字节)。当发现此错误的时候已经有很多程序员在使用这个函数了,Microsoft只好将错就错,直接把原来的API文档给改了过来。

为了解决GetVersion带来的问题,Microsoft后来开发了一个新的函数GetVersionEx,用它能够得到更详细的Windows系统的版本信息,下面我就写写GetVersionEx的使用方法。

函数原型:

BOOL GetVersionEx(POSVERSIONINFO pVersionInformation);

我们先来看看OSVERSIONINFOEX这个结构:

typedef struct {

DWORD dwOSVersionInfoSize;       //在使用GetVersionEx之前要将此初始化为结构的大小

DWORD dwMajorVersion;               //系统主版本号

DWORD dwMinorVersion;               //系统次版本号

DWORD dwBuildNumber;               //系统构建号

DWORD dwPlatformId;                  //系统支持的平台(详见附1)

TCHAR szCSDVersion[128];          //系统补丁包的名称

WORD wServicePackMajor;            //系统补丁包的主版本

WORD wServicePackMinor;            //系统补丁包的次版本

WORD wSuiteMask;                      //标识系统上的程序组(详见附2)

BYTE wProductType;                    //标识系统类型(详见附3)

BYTE wReserved;                         //保留,未使用

} OSVERSIONINFOEX, *POSVERSIONINFOEX;

这个结构在Windows 2000后出现,老版本的OSVERSIONINFO结构没有wServicePackMajor、wServicePackMinor、wSuiteMask、wProductType和wReserved这几个成员。

接着在调用函数之前先初始化结构的大小:

OSVERSIONINFOEX os;

os.dwOSVersionInfoSize=sizeof(os);

函数返回值为TRUE表示成功:

if(!GetVersionEx((OSVERSIONINFO *)&os))

{

return FALSE;

}

函数调用成功以后就可以通过OSVERSIONINFOEX来查看系统的版本信息了。

下面是一个通过系统版本来判断操作系统名称的例子:

CString getSystemName()

{

SYSTEM_INFO info;                                   //用SYSTEM_INFO结构判断64位AMD处理器
    GetSystemInfo(&info);                               //调用GetSystemInfo函数填充结构
    OSVERSIONINFOEX os;
    os.dwOSVersionInfoSize=sizeof(OSVERSIONINFOEX); 
    if(GetVersionEx((OSVERSIONINFO *)&os))                  
    {
        CString vname;

//下面根据版本信息判断操作系统名称

switch(os.dwMajorVersion){                        //判断主版本号
            case 4:
                switch(os.dwMinorVersion){                //判断次版本号
                    case 0:
                        if(os.dwPlatformId==VER_PLATFORM_WIN32_NT)
                            vname=_T("Microsoft Windows NT 4.0");                //1996年7月发布
                        else if(os.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
                            vname=_T("Microsoft Windows 95");
                        break;
                    case 10:
                        vname=_T("Microsoft Windows 98");
                        break;
                    case 90:
                        vname=_T("Microsoft Windows Me");
                        break;
                }
                break;
            case 5:
                switch(os.dwMinorVersion){               //再比较dwMinorVersion的值
                    case 0:
                        vname=_T("Microsoft Windows 2000");                    //1999年12月发布
                        break;
                    case 1:
                        vname=_T("Microsoft Windows XP");                    //2001年8月发布
                        break;
                    case 2:
                        if(os.wProductType==VER_NT_WORKSTATION && /

info.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)

vname=_T("Microsoft Windows XP Professional x64 Edition");
                        else if(GetSystemMetrics(SM_SERVERR2)==0)
                            vname=_T("Microsoft Windows Server 2003");        //2003年3月发布
                        else if(GetSystemMetrics(SM_SERVERR2)!=0)
                            vname=_T("Microsoft Windows Server 2003 R2");
                        break;
                }
                break;
            case 6:
                switch(os.dwMinorVersion){
                    case 0:
                        if(os.wProductType==VER_NT_WORKSTATION)
                            vname=_T("Microsoft Windows Vista");
                        else
                            vname=_T("Microsoft Windows Server 2008");          //服务器版本
                        break;
                    case 1:
                        if(os.wProductType==VER_NT_WORKSTATION)
                            vname=_T("Microsoft Windows 7");
                        else
                            vname=_T("Microsoft Windows Server 2008 R2");
                        break;
                }
                break;
            default:
                vname=_T("未知操作系统");
        }
        return vname;
    }
    else
        return _T("");

}

以上只能判断操作系统的名称,那如何判断它是什么版本的呢(如Home版或Professional版)。

下面这个函数就返回具体的版本名称

CString getVersionMark()

{

OSVERSIONINFOEX os;
    os.dwOSVersionInfoSize=sizeof(OSVERSIONINFOEX);
    if(GetVersionEx((OSVERSIONINFO *)&os)){
        CString vmark;

switch(os.dwMajorVersion){                //先判断操作系统版本
            case 5:
                switch(os.dwMinorVersion){
                    case 0:                  //Windows 2000
                        if(os.wSuiteMask==VER_SUITE_ENTERPRISE)
                            vmark=_T("Advanced Server");
                        break;
                    case 1:                  //Windows XP
                        if(os.wSuiteMask==VER_SUITE_EMBEDDEDNT)
                            vmark=_T("Embedded");
                        else if(os.wSuiteMask==VER_SUITE_PERSONAL)
                            vmark=_T("Home Edition");
                        else
                            vmark=_T("Professional");
                        break;
                    case 2:
                        if(GetSystemMetrics(SM_SERVERR2)==0 && /

os.wSuiteMask==VER_SUITE_BLADE)  //Windows Server 2003
                            vmark=_T("Web Edition");
                        else if(GetSystemMetrics(SM_SERVERR2)==0 && /

os.wSuiteMask==VER_SUITE_COMPUTE_SERVER)
                            vmark=_T("Compute Cluster Edition");
                        else if(GetSystemMetrics(SM_SERVERR2)==0 && /

os.wSuiteMask==VER_SUITE_STORAGE_SERVER)
                            vmark=_T("Storage Server");
                        else if(GetSystemMetrics(SM_SERVERR2)==0 && /

os.wSuiteMask==VER_SUITE_DATACENTER)
                            vmark=_T("Datacenter Edition");
                        else if(GetSystemMetrics(SM_SERVERR2)==0 && /

os.wSuiteMask==VER_SUITE_ENTERPRISE)
                            vmark=_T("Enterprise Edition");
                        else if(GetSystemMetrics(SM_SERVERR2)!=0 &&  /

os.wSuiteMask==VER_SUITE_STORAGE_SERVER)

vmark=_T("Storage Server");
                        break;
                }
                break;
            case 6:
                switch(os.dwMinorVersion){
                    case 0:
                        if(os.wProductType!=VER_NT_WORKSTATION && /

os.wSuiteMask==VER_SUITE_DATACENTER) 
                            vmark=_T("Datacenter Server");
                        else if(os.wProductType!=VER_NT_WORKSTATION &&  /

os.wSuiteMask==VER_SUITE_ENTERPRISE)
                            vmark=_T("Enterprise");
                        else if(os.wProductType==VER_NT_WORKSTATION && /

os.wSuiteMask==VER_SUITE_PERSONAL)  //Windows Vista

vmark=_T("Home");
                        break;
                }
                break;
            default:
                vmark=_T("");
        }
        return vmark;
    }
    else
        return _T("");

}

另外,操作系统的补丁包名称也可以从szCSDVersion直接获取。

程序编译出来后大家可以用不同版本的兼容模式运行这个程序,来检测结果是不是正确,兼容模式会欺骗GetVersionEx这些API函数,拿Windows 98 兼容模式来说,程序会以为自己是在Windows 98 上运行。

有什么问题请给我留言,如果在本页面下发没有看到有留言请刷新一下页面。

附1:dwPlatformId的值:

VER_PLATFORM_WIN32s (Win32s),

VER_PLATFORM_WIN32_WINDOWS (Windows 95/Windows 98),

VER_PLATFORM_WIN32_NT (Windows NT/Windows 2000),

VER_PLATFORM_WIN32_CEHH (Windows CE).

附2:wSuiteMask的值:

VER_SUITE_SMALLBUSINESS,

VER_SUITE_ENTERPRISE,

VER_SUITE_BACKOFFICE,

VER_SUITE_COMMUNICATIONS,

VER_SUITE_TERMINAL,

VER_SUITE_SMALLBUSINESS_RESTRICTED,

VER_SUITE_EMBEDDEDNT,

VER_SUITE_DATACENTER.

附3:wProductType的值:

VER_NT_WORKSTATION,

VER_NT_SERVER,

VER_NT_DOMAIN_CONTROLLER.

GetVersion和GetVersionEx的更多相关文章

  1. WindowsAPI使用详解——GetVersion|GetVersionEx 获取操作系统版本和名称

      Windows API 中有两个函数可以得到系统版本信息:GetVersion和GetVersionEx.      GetVersion这个函数曾经困扰了很多程序员,其本来设计的是在DWORD返 ...

  2. NTDLL未文档化函数RtlGetNtVersionNumbers获取操作系统版本

    作为新手,对获取操作系统版本号好奇过,因为曾经假象过一个场景:自己的程序在windows xp环境下编译,在windows 2003, windows 7,windows 8是否需要提权或者兼容处理, ...

  3. C# 获取并判断操作系统版本,解决Win10、 Windows Server 2012 R2 读取失败的方案

    Windows 8.1, Win10之后,通过GetVersion and GetVersionEx 方法获取WIndows操作系统版本号的功能需要添加manifest文件后才能查找到,不然的话会查找 ...

  4. API得到Windows版本

    API得到Windows版本 /** * Windows Version * https://msdn.microsoft.com/en-us/library/windows/desktop/dn48 ...

  5. 也谈如何获取真实正确的 Windows 系统版本号

    关于 GetVersion 系列接口 关于如何获取 Windows 系统版本号的话题,网上已经有了太多的帖子.但个人觉得总结的都不尽全面,或者没有给出比较稳定的解决方案. 众所周知,获取 Window ...

  6. 推断Windows版本号新方法

    曾经在代码中推断用户的Windows操作系统版本号都是通过GetVersion或GetVersionEx获取版本号号,然后比較. 今天偶然发如今新的Visual Studio提供了新的函数来推断系统版 ...

  7. 获取windows版本信息的做法

    作者:朱金灿 来源:http://blog.csdn.net/clever101 个人不建议用 GetVersion 或GetVersionEx 之类的 API 来获取系统版本号.注意微软也说过,这个 ...

  8. 读取注册表获取Windows系统XP/7/8/10类型(使用wcscmp比较wchar[]内容)

    很多方案是采用GetVersion.GetVersionEx这两个API来查询操作系统的版本号来判断当前的操作系统是Windows系列中的哪个,在Win10没有出现前,这种方法是行的通的,但是Win1 ...

  9. Delphi7所使用的WinAPI大全(摘自VCL源码,一共1200个函数)

    经过我整理的,去掉了A和W的重复.虽然没写注释,但以后要一个一个研究.有这些WINAPI就够用了. kernel32 = 'kernel32.dll'; gdi32 = 'gdi32.dll'; us ...

随机推荐

  1. python之类与对象(5)

    6. 类的多继承与超继承 6.1 多继承 python的类还有一个特点,就是可以继承多个类.但是我们作为测试人员,在实际中很少用到这个多继承,这里不就详细(一直都不详细,hhhh)写了.上代码: #! ...

  2. POJ_3368 Frequent values 【线段树+区间查询】

    一.题面 POJ3368 二.分析 仍然是一道只需要区间查询不需要区间修改的线段树题. 这题的题面比较特别,它是一组非减的数组.当需要去找一段区间内出现次数最多的数字时,这些数字必然是连续的,那么就可 ...

  3. Vue项目中用的Jquery.js和easing.js做的抛物线

    如果项目中还用到自有的$ <script> jQuery.noConflict();</script> //星星掉落movePathNew(args) { let self = ...

  4. js高级程序设计 笔记 --- 面向对象的程序设计

    1,理解对象 通过对象字面量的方式,创建一个对象,为它添加属性和方法: var obj = { a: 1, b:2, sayA(){ console.log(this.a)}} 1,属性类型: 数据属 ...

  5. 基于JQuery easyui,gson的批量新增/修改和删除-servlet版

    最近项目需要用到在页面进行批量操作,做了一些这方面的学习,参照网上的资料写了个小例子,记录一下: 准备 引入gson-2.6.2.jar,这里使用gson而不使用json-lib,原因是json-li ...

  6. Oracle rownum

    本问参考自Oracle中ROWNUM的使用技巧.纯属读书笔记,用于加深记忆 rownum是oracle中的一种伪列,它会根据返回的记录生成一个序列化的数字,利用rownum,我们可以得到一些原先难以得 ...

  7. Zookeeper概念学习系列之paxos协议

    不多说,直接上干货! 前言 一种最终一致的算法,paxos算法. paxos算法是由大牛lamport发明的,关于paxos算法有很多趣事.比如lamport论文最初由故事描述来引入算法,以至于那班习 ...

  8. validate表单校验插件笔记

    1validation知识点 1 validation基础 validation插件下载http://bassistance.de/jquery-plugins/jquery-plugin-valid ...

  9. 权重平等分布局And TableRow布局误区

    开头语: 本人最近在自学Android,虽然本人有2年Java Web的开发经验.但是发现Android的自学之路并不是那么平坦,我没有Android真机.但是有一个window phone的手机.开 ...

  10. pointer-events属性值详解

    其实早知道这个属性,但是一直没有去研究过.今天正好在twitter看到这个词,就去研究了下,正好解决了目前遇到的一个小难题,所以分享下.嗯,其实这是个比较简单的CSS3属性. 在某个项目中,很多元素需 ...