实战经验:在Windows 8.1/10上获取具体的系统版本号

问题

碰到这样一个问题,需要获取当前运行系统的版本号。

对于Windows系统来说,主要需要关注的是两个版本号:主版本,次版本。例如:Windows 7系统的版本号为:6.1。Windows 10的版本号为:10.0。过去我们可以使用Windows API GetVersionEx来获取系统版本,但是从Windows8.1开始,如果程序没有进行Manifest(原谅我也不知道怎么翻译这个词比较合适,所以直接用原文),则这个API将返回Windows 8的版本,也即:当你的程序跑在Windows 10上,而且程序没有Manifest,则GetVersionEx将直接返回Windows 8的版本号(6.2)。

不太明白微软这样设计的原因,但是问题确实是出现了,有时我们并不需要去判断某个特性是否在当前系统上可用,但我们需要准确的知道当前系统的版本。如何解决这个问题呢?

解决方法1:使用未文档化的API

ntdll中有一个未文档化的API,叫做RtlGetNtVersionNumbers。我们可以使用这个函数获取系统的版本号,而不需要显式的Manifest。

先来看示例代码:

实战经验:在Windows 8.1/10上获取具体的系统版本号_第1张图片

代码解释如下:

1) 因为此API从ntdll.dll中导出,所以我们首先尝试加载ntdll.dll这个文件,加载成功后,使用GetProcAddress来获取函数指针,然后进行调用。

2) 如果版本号为6.3,则表示当前系统是Windows 8。如果是10.0,则表示当前系统是Windows 10。

3) 这里需要注意的是,我没有进行完整的错误处理,代码只是演示了基本思路。

4) 另外,从MSDN中可以知道,当版本是6.3的时候,系统可能是Windows 8,也可能是Windows Server 2012 R2,所以,还需要对此种情况做进一步判断。

解决方法2:添加Manifest

这种方法就是微软所推荐的方法了。具体步骤如下:

1) 创建一个manifest文件,例如:test.manifest。

2) 将如下内容填充到test.manifest中。

实战经验:在Windows 8.1/10上获取具体的系统版本号_第2张图片

3) 在VS中,在【项目-属性-清单工具-输入输出-额外的清单文件】中指定这个test.manifest文件。

4) 重新编译。

经过以上步骤之后,我们就可以在Windows 8.1/10上准确的获取系统版本号了。添加了这个清单文件,不会影响程序在Windows 7/8上的正常运行。另外需要注意的是,当以后新的操作系统发布,我们需要根据新系统的ID对test.manifest进行修改。

总结

1) 使用未文档化的方法虽然可以获取版本号,也不需要指定Manifest,但是因为这个API不是SDK的一部分,微软有权在将来的系统中变更甚至取消这个API,所以,尽量不推荐使用此种方法。

2) 在VS2010中,使用清单的方式来获取版本号比较方便有效,但MT.exe工具有Bug,编译时会出现以下警告信息。

warning 81010002: Unrecognized Element “compatibility” in namespace

解决方法:升级VS到最新版本,或者向微软请求一个hotfix来解决此问题。

实战经验:在Windows 8.1/10上获取具体的系统版本号_第3张图片

你可能感兴趣的:(实战经验:在Windows 8.1/10上获取具体的系统版本号)