c-如何以经得起未来考验的方式确定Windows版本



我注意到GetVersionEx()已被声明为弃用。更糟糕的是,对于Windows 8.1(以及可能的未来版本),版本号受到应用程序清单的限制。

我的目标是收集用户正在运行的操作系统的分析,这样我就可以适当地针对支持。我想要一个经得起未来考验的解决方案来收集这些数据。更新清单不起作用,因为我只能更新已经发布的Windows版本的清单,而不能更新未来版本的清单。建议的替换API版本助手函数是无用的。

如何收集实际的Windows版本号?

澄清一下:我所说的"经得起未来考验",只是指我想要的东西有相当好的机会在下一个版本的Windows上运行。没有什么是确定的,但医生确实说GetVersionEx()不起作用。

MSDN有一个示例,展示了如何使用(对您的场景没有用处的)版本助手函数,但在介绍中有以下内容:

要获取操作系统的完整版本号,请在其中一个系统dll(如Kernel32.dll)上调用GetFileVersionInfo函数,然后调用VerQueryValue以获取文件版本信息的\StringFileInfo\\ProductVersion子块。

到目前为止,GetFileVersionInfoVerQueryValue函数都不推荐使用。

示例

这将从kernel32.dll中提取产品版本,并将其打印到控制台:

#pragma comment(lib, "version.lib")
static const wchar_t kernel32[] = L"\kernel32.dll";
wchar_t *path = NULL;
void *ver = NULL, *block;
UINT n;
BOOL r;
DWORD versz, blocksz;
VS_FIXEDFILEINFO *vinfo;
path = malloc(sizeof(*path) * MAX_PATH);
if (!path)
    abort();
n = GetSystemDirectory(path, MAX_PATH);
if (n >= MAX_PATH || n == 0 ||
    n > MAX_PATH - sizeof(kernel32) / sizeof(*kernel32))
    abort();
memcpy(path + n, kernel32, sizeof(kernel32));
versz = GetFileVersionInfoSize(path, NULL);
if (versz == 0)
    abort();
ver = malloc(versz);
if (!ver)
    abort();
r = GetFileVersionInfo(path, 0, versz, ver);
if (!r)
    abort();
r = VerQueryValue(ver, L"\", &block, &blocksz);
if (!r || blocksz < sizeof(VS_FIXEDFILEINFO))
    abort();
vinfo = (VS_FIXEDFILEINFO *) block;
printf(
    "Windows version: %d.%d.%d",
    (int) HIWORD(vinfo->dwProductVersionMS),
    (int) LOWORD(vinfo->dwProductVersionMS),
    (int) HIWORD(vinfo->dwProductVersionLS));
free(path);
free(ver);

Yikes,目前接受的答案过于复杂。以下是如何快速可靠地获得当前窗口的版本(带有内部版本号),而不需要清单和其他无意义的技巧。适用于Windows 2000及更新版本(即现有的所有版本的Windows)。

简短回答:使用RtlGetVersion

没有Windows驱动程序开发工具包?然后它就没有包含头和使用函数那么简单了。以下是使用和不使用WDK时的操作方法。

使用WDK,包括:

// Required for RtlGetVersion()
#pragma comment(lib, "ntdll.lib")
#include <Ntddk.h>

不带WDK,包括:

// Required for RtlGetVersion()
#pragma comment(lib, "ntdll.lib")
// Define the function because we don't have the driver development
// kit headers. We could probably acquire them but it makes development
// onboarding a pain in the ass for new employees.
extern "C" {
typedef LONG NTSTATUS, *PNTSTATUS;
#define STATUS_SUCCESS (0x00000000)
// Windows 2000 and newer
NTSYSAPI NTSTATUS NTAPI RtlGetVersion(PRTL_OSVERSIONINFOEXW lpVersionInformation);
}

现在,只需获得准确的版本详细信息:

RTL_OSVERSIONINFOEXW osVers;
osVers.dwOSVersionInfoSize = sizeof(osVers);
// fill the structure with version details
NTSTATUS status = RtlGetVersion(&osVers);
// this should always succeed
assert(status == STATUS_SUCCESS);

osVers变量现在包含准确的主要、次要和内部版本号。无需读取文件版本,也无需在运行时动态加载库。

请将此项投票高于其他答案,以便在应用程序中使用此正确代码,而不是使用rube-goldberg其他答案。谢谢

最新更新