GetVersionEx等api的windows兼容问题

概括

在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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Z小偉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值