Windows 8.1中获得系统版本信息的方法

Tips

在Windows 8.1之前的系统版本上,我们一直可以使用 GetVersionEx.aspx) 这个函数来获取当前系统的MajorVersion和MinorVersion。但是当Windows系统来到8.1时代,这个API似乎就不好用了。如果在Windows 8.1上调用这个函数,我们更有可能获得的版本号是Windows 8的版本6.2,而不是我们想要的6.3。在MSDN上提供了这样一段说明:

With the release of Windows 8.1, the behavior of the GetVersionEx API has changed in the value it will return for the operating system version. The value returned by the GetVersionEx function now depends on how the application is manifested.

Applications not manifested for Windows 8.1 will return the Windows 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersionEx will always return the version that the application is manifested for in future releases.

好了,既然微软都这么说了,也没办法,还好微软也给我们提供了另一套函数,叫做Version Helper functions.aspx) ,看起来是一套很不错的API,能帮助我们方便的判断系统版本。但是,仔细一看,这套函数需要头文件VersionHelpers.h,而这个文件是 Windows 8.1 software development kit 的一部分。对于使用低版本的VS还得装新版SDK,岂不麻烦。那么我们希望能找到一套更好的解决方法。

我第一个能想到了,当然就是万能的WMI,使用Win32_OperatingSystem class中的Version可以获得一个形如6.3.9600的字符串,我们就能通过解析这个获得系统的版本了。但是说实话,不到万不得已我不太喜欢用WMI这套API,总感觉为了一个小功能,牵扯了一堆东西。

那么第二套方案,是我觉得比较满意的,那就是调用VerSetConditionMask.aspx)和VerifyVersionInfo.aspx)来完成对系统版本的判断。具体做法如下:

1
2
3
4
5
6
7
8
9
10
11
12
BOOL IsWindows8Point1()
{
OSVERSIONINFOEX version_info = {0};
version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
version_info.dwMajorVersion = 6;
version_info.dwMinorVersion = 3;
ULONGLONG mask = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
mask = VerSetConditionMask(mask, VER_MINORVERSION, VER_EQUAL);
return VerifyVersionInfo(&version;_info, VER_MAJORVERSION | VER_MINORVERSION, mask);
}


那么,我们就可以用这个函数来判断系统是否是Windows 8.1,如果不是,我们就可以用老办法,GetVersionEx来获得系统的版本号作判断了。当然了,大家看到这估计也能看出,我们自己也能用这两个函数实现一套所谓的Version Helper functions。举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
BOOL WINAPI IsWindowsVersionOrGreater(
WORD wMajorVersion,
WORD wMinorVersion,
WORD wServicePackMajor
)
{
OSVERSIONINFOEX version_info = { 0 };
version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
version_info.dwMajorVersion = wMajorVersion;
version_info.dwMinorVersion = wMinorVersion;
version_info.wServicePackMajor = wServicePackMajor;

ULONGLONG mask = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
mask = VerSetConditionMask(mask, VER_MINORVERSION, VER_GREATER_EQUAL);
mask = VerSetConditionMask(mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);

return VerifyVersionInfo(&version;_info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, mask);
}

怎么样,是不是达到了以假乱真的效果了。那么最后,咱再看看这么写出来的API的效果如何:

20140413233019

===============想睡觉的分割线====================

更新另外一个方法,在网上看到的,感觉也还行。只不过需要引入其他DLL,可以作为备选方案。

1
2
3
4
5
6
7
8
9
10
11
12
13
ULONG MyGetVersion()
{
LPBYTE raw_data;
ULONG retval = 0;
if (NetWkstaGetInfo(NULL, 100, &raw;_data) == NERR_Success) {
WKSTA_INFO_100 * ws_info = reinterpret_cast(raw_data);
retval = (ws_info->wki100_ver_major << 16) | ws_info->wki100_ver_minor;
NetApiBufferFree(raw_data);
return retval;
}
return retval;
}

Post Directory

Article directory