windows 在 c++ win32 中获取所有版本的 win 的操作系统?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2877295/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 14:29:51  来源:igfitidea点击:

Get OS in c++ win32 for all versions of win?

c++windowswinapioperating-system

提问by extintor

How to get the OS version for all windows, at least the name for win95,98,me,xp,vista,7?

如何获取所有 Windows 的操作系统版本,至少是 win95,98,me,xp,vista,7 的名称?

Im using visual c++ 2010 and I want to include this feature in a pure win32 app.

我使用的是 Visual C++ 2010,我想在纯 win32 应用程序中包含此功能。

回答by Benjamin Foster

How about something like this:

这样的事情怎么样:

#include <windows.h>
#include <string>
#include <lm.h>
#pragma comment(lib, "netapi32.lib")

bool GetWinMajorMinorVersion(DWORD& major, DWORD& minor)
{
    bool bRetCode = false;
    LPBYTE pinfoRawData = 0;
    if (NERR_Success == NetWkstaGetInfo(NULL, 100, &pinfoRawData))
    {
        WKSTA_INFO_100* pworkstationInfo = (WKSTA_INFO_100*)pinfoRawData;
        major = pworkstationInfo->wki100_ver_major;
        minor = pworkstationInfo->wki100_ver_minor;
        ::NetApiBufferFree(pinfoRawData);
        bRetCode = true;
    }
    return bRetCode;
}


std::string GetWindowsVersionString()
{
    std::string     winver;
    OSVERSIONINFOEX osver;
    SYSTEM_INFO     sysInfo;
    typedef void(__stdcall *GETSYSTEMINFO) (LPSYSTEM_INFO);

    __pragma(warning(push))
    __pragma(warning(disable:4996))
    memset(&osver, 0, sizeof(osver));
    osver.dwOSVersionInfoSize = sizeof(osver);
    GetVersionEx((LPOSVERSIONINFO)&osver);
    __pragma(warning(pop))
    DWORD major = 0;
    DWORD minor = 0;
    if (GetWinMajorMinorVersion(major, minor))
    {
        osver.dwMajorVersion = major;
        osver.dwMinorVersion = minor;
    }
    else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2)
    {
        OSVERSIONINFOEXW osvi;
        ULONGLONG cm = 0;
        cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_EQUAL);
        ZeroMemory(&osvi, sizeof(osvi));
        osvi.dwOSVersionInfoSize = sizeof(osvi);
        osvi.dwMinorVersion = 3;
        if (VerifyVersionInfoW(&osvi, VER_MINORVERSION, cm))
        {
            osver.dwMinorVersion = 3;
        }
    }

    GETSYSTEMINFO getSysInfo = (GETSYSTEMINFO)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetNativeSystemInfo");
    if (getSysInfo == NULL)  getSysInfo = ::GetSystemInfo;
    getSysInfo(&sysInfo);

    if (osver.dwMajorVersion == 10 && osver.dwMinorVersion >= 0 && osver.wProductType != VER_NT_WORKSTATION)  winver = "Windows 10 Server";
    if (osver.dwMajorVersion == 10 && osver.dwMinorVersion >= 0 && osver.wProductType == VER_NT_WORKSTATION)  winver = "Windows 10";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3 && osver.wProductType != VER_NT_WORKSTATION)  winver = "Windows Server 2012 R2";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3 && osver.wProductType == VER_NT_WORKSTATION)  winver = "Windows 8.1";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2 && osver.wProductType != VER_NT_WORKSTATION)  winver = "Windows Server 2012";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2 && osver.wProductType == VER_NT_WORKSTATION)  winver = "Windows 8";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1 && osver.wProductType != VER_NT_WORKSTATION)  winver = "Windows Server 2008 R2";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1 && osver.wProductType == VER_NT_WORKSTATION)  winver = "Windows 7";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0 && osver.wProductType != VER_NT_WORKSTATION)  winver = "Windows Server 2008";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0 && osver.wProductType == VER_NT_WORKSTATION)  winver = "Windows Vista";
    if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2 && osver.wProductType == VER_NT_WORKSTATION
        &&  sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)  winver = "Windows XP x64";
    if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2)   winver = "Windows Server 2003";
    if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1)   winver = "Windows XP";
    if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 0)   winver = "Windows 2000";
    if (osver.dwMajorVersion < 5)   winver = "unknown";

    if (osver.wServicePackMajor != 0)
    {
        std::string sp;
        char buf[128] = { 0 };
        sp = " Service Pack ";
        sprintf_s(buf, sizeof(buf), "%hd", osver.wServicePackMajor);
        sp.append(buf);
        winver += sp;
    }

    return winver;
}

回答by Paul Dixon

Take a look at the MSDN article Getting the System Version

看一下MSDN文章获取系统版本

While the article only mentions currently supported Windows versions, see this knowledge base articlefor the numbers you'll see in the OSVERSIONINFO structure for Win 95, 98 etc.

虽然该文章仅提及当前支持的 Windows 版本,但请参阅此知识库文章,了解您将在 Win 95、98 等的 OSVERSIONINFO 结构中看到的数字。

回答by c00000fd

It all depends on why you need to know OS version:

这完全取决于您为什么需要知道操作系统版本:

  • To use certain feature that may not be available in older OS.In this case I would strongly suggest checking if the API itself is available using LoadLibraryand GetProcAddressfunctions. Otherwise, I guess you can dynamically import RtlGetVersionfrom ntdll.dlland use it, but again, there're too many ways it can return inaccurate information (the ones that come to mind are compatibility mode and API trampolinesthat can be installed by malware, AVP, and even OS itself.)

  • For display purposes only.(ex: in Aboutwindow for your app, or to include it in your diagnostic event log, etc.) In this case a quick and easy hackis to read it as text from the System Registry:

  • 使用旧操作系统中可能不可用的某些功能。在这种情况下,我强烈建议使用LoadLibraryGetProcAddress函数检查 API 本身是否可用。否则,我想你可以动态导入RtlGetVersionntdll.dll和使用它,但同样,有太多种方法可以返回不准确的信息(即脑海中出现兼容模式和那些API蹦床,可以通过恶意软件,AVP进行安装,甚至操作系统本身。)

  • 仅用于展示目的。(例如:在About您的应用程序的窗口中,或将其包含在您的诊断事件日志中等)在这种情况下,一个快速而简单的技巧是从系统注册表中将其作为文本读取:

enter image description here

在此处输入图片说明

The downside of this approach though, is that the names and numbers can be localized for the end-user's system.

但是,这种方法的缺点是可以为最终用户的系统本地化名称和号码。

Use the following key that is available since Windows XP:

使用自 Windows XP 起可用的以下密钥:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion

and its following REG_SZ(or string) values:

及其以下REG_SZ(或字符串)值:

  • ProductName= for OS name
  • CurrentVersion= for OS version
  • BuildLab= for full build number
  • BuildLabEx= extended build number (available since Windows 7)
  • ReleaseId= Release number (available since Windows 10)
  • ProductName= 操作系统名称
  • CurrentVersion= 操作系统版本
  • BuildLab= 完整版本号
  • BuildLabEx= 扩展版本号(自 Windows 7 起可用)
  • ReleaseId= 版本号(自 Windows 10 起可用)