自从Windows 8.1废弃了GetVersionEx,必须写manifest才能正确获取系统版本之后,如何始终正确获取系统版本就是一个让人头疼的话题。大概有以下几种尝试。
实际上,有一种方法微软可能懒得造假,那就是VerQueryValue读取kernel32.dll等系统文件的产品版本号dwProductVersionMS/LS。有人可能会说,那以后微软不在这里写系统版本了怎么办?实际上,微软已经公开了这个做法,将来不可能大改,否则将有兼容性问题。
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
一般来说,系统文件版本号的格式是major.minor.build.rev。不过,已淘汰的Windows 95/98/Me并不遵守这个约定,它们的系统文件版本号是major.minor.0.build。不过,可以通过dwFileOS是否设置有VOS_DOS位来判断Windows 95/98/Me,而且它们的版本号都是4.x,现在的操作系统版本号早已超过5.0。
不建议读取dwFileVersionMS/LS,它是kernel32.dll文件本身的版本号,而不是系统的版本号。
为了保证可靠,这里也不推荐使用GetFileVersionInfo,因为Windows也可以在这个函数上做手脚。建议直接读取已加载的kernel32.dll模块的资源段,方法如下:
#include <windows.h>
#include <tchar.h>
#pragma comment(lib, "version.lib")
BOOL CheckModuleProductVersion(LPCTSTR modname, WORD major, WORD minor, WORD build, WORD rev)
{
HMODULE hmod = GetModuleHandle(modname);
if (!hmod)
return FALSE;
LPVOID verblock = LockResource(LoadResource(hmod, FindResource(hmod, MAKEINTRESOURCE(1), MAKEINTRESOURCE(RT_VERSION))));
if (!verblock)
return FALSE;
VS_FIXEDFILEINFO *pvsffi = NULL;
UINT szvsffi = 0;
if (!VerQueryValue(verblock, _T("\\"), (LPVOID*)&pvsffi, &szvsffi))
return FALSE;
ULONGLONG ullProductVersion = ((ULONGLONG)pvsffi->dwProductVersionMS << 32) + pvsffi->dwProductVersionLS;
ULONGLONG ullReqVersion = ((ULONGLONG)major << 48) + ((ULONGLONG)minor << 32) + ((ULONGLONG)build << 16) + rev;
if (ullProductVersion < ullReqVersion)
return FALSE;
return TRUE;
}
BOOL GetOSVersion(PULONGLONG pullProductVersion, PBOOL piswin9x)
{
#pragma comment(lib, "version.lib")
HMODULE hmod = GetModuleHandle(_T("kernel32.dll"));
if (!hmod)
return FALSE;
LPVOID verblock = LockResource(LoadResource(hmod, FindResource(hmod, MAKEINTRESOURCE(1), MAKEINTRESOURCE(RT_VERSION))));
if (!verblock)
return FALSE;
VS_FIXEDFILEINFO *pvsffi = NULL;
UINT szvsffi = 0;
if (!VerQueryValue(verblock, _T("\\"), (LPVOID*)&pvsffi, &szvsffi))
return FALSE;
if (pullProductVersion)
*pullProductVersion = ((ULONGLONG)pvsffi->dwProductVersionMS << 32) + pvsffi->dwProductVersionLS;
if (piswin9x)
*piswin9x = !!(pvsffi->dwFileOS & VOS_DOS);
return TRUE;
}
BOOL Is_Win7_OrGreater()
{
ULONGLONG osver = 0;
if (!GetOSVersion(&osver, NULL))
return FALSE;
return osver >= (6UI64 << 48) + (1UI64 << 32);
}
</tchar.h></windows.h>