概括
在win8.1和win10系统中,GetVersion和GetVersionEx函数废弃,使用这些废弃函数在高版本系统中无法获取到正确的系统版本信息,故使用了新的获取版本的函数。但是为了兼容老版本系统,我们不得不使用这2个函数。所以就需要使用其它方法在高版本系统中,可以获取到对应的版本。
代码
定义
class Environment
{
public:
static bool isWinNTFamily();
static bool isWin2000();
static bool isWinXP();
static bool isVista();
static bool isVistaOrLater();
static bool isWin7();
static bool isWin8();
static bool isWin10();
static bool isWin2003Server();
static bool isWin2008Server();
static bool isWin2012Server();
static bool isWin2016Server();
private:
static void init();
private:
static OSVERSIONINFOEX osVersionInfo_;
};
实现
OSVERSIONINFOEX Environment::osVersionInfo_ = { 0 };
void Environment::init()
{
if (osVersionInfo_.dwOSVersionInfoSize == 0) {
osVersionInfo_.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (!GetVersionEx((LPOSVERSIONINFO)&osVersionInfo_)) {
osVersionInfo_.dwOSVersionInfoSize = 0;
}
}
}
bool Environment::isWinNTFamily()
{
init();
return osVersionInfo_.dwPlatformId == VER_PLATFORM_WIN32_NT;
}
bool Environment::isWin2000()
{
init();
return osVersionInfo_.dwMajorVersion == 5 && osVersionInfo_.dwMinorVersion == 0;
}
bool Environment::isWinXP()
{
init();
return ((osVersionInfo_.dwMajorVersion == 5) && (osVersionInfo_.dwMinorVersion == 1) && isWinNTFamily());
}
bool Environment::isWin2003Server()
{
init();
return ((osVersionInfo_.dwMajorVersion == 5) && (osVersionInfo_.dwMinorVersion == 2) && isWinNTFamily());
}
bool Environment::isVistaOrLater()
{
init();
return osVersionInfo_.dwMajorVersion >= 6;
}
bool Environment::isWin10() {
init();
return osVersionInfo_.dwMajorVersion == 10 && osVersionInfo_.dwMinorVersion == 0 && osVersionInfo_.wProductType == VER_NT_WORKSTATION;
}
bool Environment::isWin2016Server() {
init();
return osVersionInfo_.dwMajorVersion == 10 && osVersionInfo_.dwMinorVersion == 0 && osVersionInfo_.wProductType != VER_NT_WORKSTATION;
}
bool Environment::isWin7() {
init();
return osVersionInfo_.dwMajorVersion == 6 && osVersionInfo_.dwMinorVersion == 1 && osVersionInfo_.wProductType == VER_NT_WORKSTATION;
}
bool Environment::isWin2008Server() {
init();
return (osVersionInfo_.dwMajorVersion == 6 && osVersionInfo_.dwMinorVersion == 0 &&
osVersionInfo_.wProductType != VER_NT_WORKSTATION) || (osVersionInfo_.dwMajorVersion == 6 &&
osVersionInfo_.dwMinorVersion == 1 && osVersionInfo_.wProductType != VER_NT_WORKSTATION);
}
bool Environment::isWin2012Server() {
init();
return (osVersionInfo_.dwMajorVersion == 6 && osVersionInfo_.dwMinorVersion == 2 &&
osVersionInfo_.wProductType != VER_NT_WORKSTATION) || (osVersionInfo_.dwMajorVersion == 6 &&
osVersionInfo_.dwMinorVersion == 3 && osVersionInfo_.wProductType != VER_NT_WORKSTATION);
}
bool Environment::isWin8() {
init();
return (osVersionInfo_.dwMajorVersion == 6 && osVersionInfo_.dwMinorVersion == 2 &&
osVersionInfo_.wProductType == VER_NT_WORKSTATION) || (osVersionInfo_.dwMajorVersion == 6 &&
osVersionInfo_.dwMinorVersion == 3 && osVersionInfo_.wProductType == VER_NT_WORKSTATION);
}
bool Environment::isVista() {
init();
return osVersionInfo_.dwMajorVersion == 6 && osVersionInfo_.dwMinorVersion == 0 &&
osVersionInfo_.wProductType == VER_NT_WORKSTATION;
}
使用以上代码是可以正确获取到win8.1之前系统的所有版本,但是win8.1和win10的系统版本获取到的是错误的,获取到的都是win8系统的版本(6.2.0.0 )。为了获取正确的版本号,我们需要在应用中加入manifest文件。在vs的中间目录里会有一个应用程序的manifest文件,假如你的程序名是testlwkit.exe,那么你的manifest文件就是testlwkit.exe.intermediate.manifest。在这个文件当中加入如下代码:
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
完整的xml文件就如下所示:
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level='requireAdministrator' uiAccess='false' />
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*' />
</dependentAssembly>
</dependency>
</assembly>
把这个manifest文件加入到资源文件中,取名为MANIFEST,重新编译testlwkit项目,就可以在win8.1和win10系统当中获取到正确的系统版本号。
参考:http://docs.microsoft.com/zh-cn/windows/desktop/SysInfo/targeting-your-application-at-windows-8-1