【问题标题】:Get OS in c++ win32 for all versions of win?为所有版本的win获取c ++ win32中的操作系统?
【发布时间】:2011-02-22 01:36:52
【问题描述】:

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

我正在使用 Visual c++ 2010,我想将此功能包含在纯 win32 应用程序中。

【问题讨论】:

标签: c++ windows winapi operating-system


【解决方案1】:

这样的事情怎么样:

#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;
}

【讨论】:

  • 谢谢。效果很好!
【解决方案2】:

【讨论】:

  • 它确实说:Minimum supported client: Windows 2000 Professional
  • 相当肯定 API 从 Windows 95 开始就在 Win32 API 中
  • 我不知道为什么他们修改了所有 MSDN 文档,将所有“旧”API 的“最低支持客户端”语音更改为 Windows 2000 Professional。这太愚蠢了,没有必要这样做。
  • 注意:GetVersionEx 不能保证在 Windows 8 之后可用...它被 Version Helper API 函数取代,这些函数实际上不会返回您的操作系统版本号...arrg。跨度>
  • GetVersionEx 已被弃用,它将为高于 8 的任何 Windows 返回 8,除非您在清单中明确定位更高版本。
【解决方案3】:

看看MSDN文章Getting the System Version

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

【讨论】:

    【解决方案4】:

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

    • 使用旧操作系统中可能不可用的某些功能。在这种情况下,我强烈建议使用LoadLibraryGetProcAddress 函数检查API 本身是否可用。否则,我想您可以从ntdll.dll 动态导入RtlGetVersion 并使用它,但同样,它可以返回不准确信息的方式太多(想到的是兼容模式和API trampolines 可以由恶意软件、AVP 甚至操作系统本身安装。)

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

    不过,这种方法的缺点是名称和数字可以针对最终用户的系统进行本地化。

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

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
    

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

    • ProductName = 操作系统名称
    • CurrentVersion = 适用于操作系统版本
    • BuildLab = 完整版本号
    • BuildLabEx = 扩展版本号(自 Windows 7 起可用)
    • ReleaseId = 版本号(自 Windows 10 起可用)

    【讨论】:

      【解决方案5】:

      我遇到了类似的问题。这是一些支持 Win 11 的代码。它不适用于服务器版本,但添加此功能很容易实现(只是服务器的另一个映射)。

       // To Workaround Win 10 problem for User Mode VerifyVersionInfo
      bool VerifyWindowsVersionInfo(PRTL_OSVERSIONINFOEXW versionInfo, ULONG typeMask, ULONGLONG conditionMask)
      {
          HMODULE hMod = nullptr;
          if ((TRUE != ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, L"ntdll.dll", &hMod)) || !hMod)
              return false;
      
          typedef NTSTATUS(WINAPI* _RtlVerifyVersionInfo)(PRTL_OSVERSIONINFOEXW, ULONG, ULONGLONG);
          const auto RtlVerifyVersionInfo =
              reinterpret_cast<_RtlVerifyVersionInfo>(::GetProcAddress(hMod, "RtlVerifyVersionInfo"));
      
          if (!RtlVerifyVersionInfo)
              return false;
      
          return NT_SUCCESS(RtlVerifyVersionInfo(versionInfo, typeMask, conditionMask));
      }
      
      bool IsWindowsVersionOrGreater(int wMajorVersion, int wMinorVersion, int wBuildNumber, int wServicePackMajor)
      {
          RTL_OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
          osvi.dwMajorVersion = wMajorVersion;
          osvi.dwMinorVersion = wMinorVersion;
          osvi.dwBuildNumber = wBuildNumber;
          osvi.wServicePackMajor = static_cast<WORD>(wServicePackMajor);
      
          DWORDLONG dwlConditionMask = 0;
          VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
          VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
          VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
          VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
      
          return VerifyWindowsVersionInfo(&osvi,
              VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER | VER_SERVICEPACKMAJOR,
              dwlConditionMask);
      
      }
      
      std::wstring GetVerbalOsVersion()
      {
          // see https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms724832(v=vs.85).aspx for details
          using OsMajorVersion = int;
          using OsMinorVersion = int;
          using OsBuildVersion = int;
          using OsServicePackMajorVersion = int;
      
          using VersionStrWithNumberPair =
              std::pair<std::wstring, std::tuple<OsMajorVersion, OsMinorVersion, OsBuildVersion, OsServicePackMajorVersion>>;
      
      
          const auto win11BuildNumber = 22000;
      
          const std::vector<VersionStrWithNumberPair> winVersionMapping = {
              {L"Windows 11 ",
               std::make_tuple(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), win11BuildNumber, 0)},
              {L"Windows 10 ", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0, 0)},
      
              {L"Windows 8.1", std::make_tuple(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0, 0)},
              {L"Windows 8 ", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0, 0)},
      
              {L"Windows 7  Service Pack 1", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0, 1)},
              {L"Windows 7 ", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0, 0)},
      
              {L"Windows Vista Service Pack 2",
               std::make_tuple(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 2)},
              {L"Windows Vista Service Pack 1",
               std::make_tuple(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 1)},
              {L"Windows Vista", std::make_tuple(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 0)},
      
              {L"Windows XP  Service Pack 3",
               std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 3)},
              {L"Windows XP Service Pack 2",
               std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 2)},
              {L"Windows XP Service Pack 1",
               std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 1)},
              {L"Windows XP ", std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 0)} };
      
          const auto it = std::find_if(std::begin(winVersionMapping),
              std::end(winVersionMapping),
              [](const VersionStrWithNumberPair& el)
              {
                  return IsWindowsVersionOrGreater(std::get<0>(el.second),
                      std::get<1>(el.second),
                      std::get<2>(el.second),
                      std::get<3>(el.second));
              });
      
          if (it == std::end(winVersionMapping))
              return L"Unknown windows version";
      
          return it->first;
      }
      

      【讨论】:

        猜你喜欢
        • 2018-05-14
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 2019-01-19
        • 2011-09-13
        • 1970-01-01
        • 2010-10-08
        • 1970-01-01
        相关资源
        最近更新 更多