cpp
复制代码
#include<iostream>
#include<string>
#include <windows.h>
// Refer: https://stackoverflow.com/questions/36543301/detecting-windows-10-version/36545162#36545162
typedef LONG NTSTATUS, * PNTSTATUS;
#define STATUS_SUCCESS (0x00000000)
// GetVersionEx 和 VerifyVersionInfo 的底层
// 随着 Windows 8.1 的发布,GetVersionEx API 的行为在操作系统版本返回的值中已更改。 GetVersionEx 函数返回的值现在取决于应用程序的清单方式。
// 未为 Windows 8.1 或 Windows 10 清单的应用程序将返回 Windows 8 OS 版本值(6.2)。
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOEXW);
RTL_OSVERSIONINFOEXW GetRealOSVersion() {
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
if (hMod) {
RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
if (fxPtr != nullptr) {
RTL_OSVERSIONINFOEXW rovi = { 0 };
rovi.dwOSVersionInfoSize = sizeof(rovi);
if (STATUS_SUCCESS == fxPtr(&rovi)) {
return rovi;
}
}
}
RTL_OSVERSIONINFOEXW rovi = { 0 };
return rovi;
}
bool OpenRegistryKey(HKEY hKey, const char* szKeyName, HKEY* phKey)
{
// 打开注册表项
LONG result = RegOpenKeyEx(
hKey,
szKeyName,
0,
KEY_READ,
phKey
);
if (result != ERROR_SUCCESS) {
return false;
}
return true;
}
bool GetDisplayVersion(HKEY hKey, char* szDisplayVersion, size_t bufferSize)
{
// Ref: https://stackoverflow.com/questions/73436713/how-to-get-the-correct-windows-version-from-command-line
// Apparently only works in version 20H2 and above.
TCHAR displayVersion[256] = { 0 };
DWORD regBufferSize = sizeof(displayVersion);
DWORD valueType;
// 读取注册表值
HRESULT result = RegQueryValueEx(
hKey,
TEXT("DisplayVersion"),
nullptr,
&valueType,
reinterpret_cast<LPBYTE>(displayVersion),
®BufferSize
);
if (result == ERROR_SUCCESS && valueType == REG_SZ) {
strncpy_s(szDisplayVersion, bufferSize, displayVersion, sizeof(displayVersion));
return true;
}
return false;
}
bool GetProductName(HKEY hKey, char* szProductName, size_t bufferSize)
{
TCHAR productName[256] = { 0 };
DWORD regBufferSize = sizeof(productName);
DWORD valueType;
// 读取注册表值
HRESULT result = RegQueryValueEx(
hKey,
TEXT("ProductName"),
nullptr,
&valueType,
reinterpret_cast<LPBYTE>(productName),
®BufferSize
);
if (result == ERROR_SUCCESS && valueType == REG_SZ) {
strncpy_s(szProductName, bufferSize, productName, sizeof(productName));
return true;
}
return false;
}
bool GetCurrentBuildNumber(HKEY hKey, char* szCurrentBuildNumber, size_t bufferSize)
{
TCHAR currentBuildNumber[256] = { 0 };
DWORD regBufferSize = sizeof(currentBuildNumber);
DWORD valueType;
// 读取注册表值
HRESULT result = RegQueryValueEx(
hKey,
TEXT("CurrentBuildNumber"),
nullptr,
&valueType,
reinterpret_cast<LPBYTE>(currentBuildNumber),
®BufferSize
);
if (result == ERROR_SUCCESS && valueType == REG_SZ) {
strncpy_s(szCurrentBuildNumber, bufferSize, currentBuildNumber, sizeof(currentBuildNumber));
return true;
}
return false;
}
bool GetUBR(HKEY hKey, DWORD& ubr) {
DWORD bufferSize = sizeof(DWORD);
DWORD valueType;
// 读取注册表值
LONG result = RegQueryValueEx(
hKey,
TEXT("UBR"),
nullptr,
&valueType,
reinterpret_cast<LPBYTE>(&ubr),
&bufferSize
);
if (result == ERROR_SUCCESS && valueType == REG_DWORD) {
return true;
}
return false;
}
// Ref: https://stackoverflow.com/questions/69373447/is-there-an-official-way-to-detect-windows-11
// Convert from: https://en.wikipedia.org/wiki/List_of_Microsoft_Windows_versions
// 这里有更加简洁的 https://www.gaijin.at/en/infos/windows-version-numbers
// 这里有更多的 https://www.gaijin.at/en/infos/windows-version-numbers
#include<map>
#include<string>
class WindowsVersions {
public:
static std::map<int, std::string> getWindowsVersions() {
std::map<int, std::string> windowsVersions;
// Non-NT Windows versions
windowsVersions[102] = "Windows for Workgroups 3.1";
windowsVersions[103] = "Windows 3.1";
windowsVersions[153] = "Windows 3.2";
windowsVersions[300] = "Windows for Workgroups 3.11";
// NT-based Windows versions
windowsVersions[511] = "Windows NT 3.1";
windowsVersions[528] = "Windows NT 3.1 Service Pack 3";
windowsVersions[807] = "Windows NT 3.5";
windowsVersions[950] = "Windows 95";
windowsVersions[1057] = "Windows NT 3.51 Workstation";
windowsVersions[1381] = "Windows NT 4.0 Workstation";
windowsVersions[1998] = "Windows 98";
windowsVersions[2195] = "Windows 2000 Professional";
windowsVersions[2222] = "Windows 98 Second Edition";
windowsVersions[2600] = "Windows XP";
windowsVersions[2700] = "Windows XP Media Center Edition 2005";
windowsVersions[2710] = "Windows XP Media Center Edition 2005 Update Rollup 2";
windowsVersions[3000] = "Windows Me";
windowsVersions[3790] = "Windows XP Professional x64 Edition/Windows Server 2003";
windowsVersions[6000] = "Windows Vista/Windows Server 2008";
windowsVersions[6001] = "Windows Vista/Windows Server 2008 Service Packs 1";
windowsVersions[6002] = "Windows Vista, Service Pack 2";//Windows Vista and Windows Server 2008 originally had the build number 6000 when they were first released; the build number was increased by one with each of the two subsequent Service Packs.
windowsVersions[6003] = "Windows Server 2008 Service Pack 2, Rollup KB4489887";
windowsVersions[7600] = "Windows 7";
windowsVersions[7601] = "Windows 7, Service Pack 1";// Windows 7 and Windows Server 2008 R2 originally had the build number 7600 when they were first released; the build number was increased to 7601 with the release of Service Pack 1.
windowsVersions[8400] = "Windows Home Server 2011";
windowsVersions[9200] = "Windows 8/Windows Server 2012";
windowsVersions[9600] = "Windows 8.1";
windowsVersions[10240] = "Windows 10 version 1507";
windowsVersions[10586] = "Windows 10 version 1511";
windowsVersions[14393] = "Windows 10 version 1607";
windowsVersions[15063] = "Windows 10 version 1703";
windowsVersions[16299] = "Windows 10 version 1709";
windowsVersions[17134] = "Windows 10 version 1803";
windowsVersions[17763] = "Windows 10 version 1809";
windowsVersions[18362] = "Windows 10 version 1903";
windowsVersions[18363] = "Windows 10 version 1909";
windowsVersions[19041] = "Windows 10 version 2004";
windowsVersions[19042] = "Windows 10 version 20H2";
windowsVersions[19043] = "Windows 10 version 21H1";
windowsVersions[19044] = "Windows 10 version 21H2";
windowsVersions[19045] = "Windows 10 version 22H2";
windowsVersions[20348] = "Windows Server 2022 21H2";
windowsVersions[22000] = "Windows 11 21H2";
windowsVersions[22621] = "Windows 11 22H2";
windowsVersions[22631] = "Windows 11 23H2";
windowsVersions[25398] = "Windows Server 23H2";
windowsVersions[26100] = "Windows 11 24H2";
return windowsVersions;
}
};
int main()
{
// Ref: https://stackoverflow.com/questions/36543301/detecting-windows-10-version/36545162#36545162
HKEY hKey;
// 打开注册表项
if (!OpenRegistryKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", &hKey)) {
return 1;
}
// DisplayVersion
char szDisplayVersion[256];
if (GetDisplayVersion(hKey, szDisplayVersion, sizeof(szDisplayVersion))) {
printf("DisplayVersion: %s\n", szDisplayVersion); // 22H2之类的版本号
}
// ProductName
char szProductName[256];
if (GetProductName(hKey, szProductName, sizeof(szDisplayVersion))) {
printf("ProductName: %s\n", szProductName); // 产品名,不准确 比如Windows11 显示的是Windows 10;Windows 8显示的是Windows 6.2
// 此外还有很多用户拿到的系统ProductName为Windows3.1,但是GetVersionEx获取到的为Windows 6.1 Service Pack 1,推测系统为Windows 7 SP1
// 同样的,有ProductName为Windows Sever 2000的玩家,但是GetVersionEx获取到的为Windows 6.1 Service Pack 1
// 因此注册表不准确
}
// CurrentBuildNumber
char szCurrentBuildNumber[256];
if (GetCurrentBuildNumber(hKey, szCurrentBuildNumber, sizeof(szCurrentBuildNumber))) {
printf("CurrentBuildNumber: %s\n", szCurrentBuildNumber);
}
// UBR
DWORD ubr = 0;
if (GetUBR(hKey, ubr)) {
printf("UBR: %d\n", ubr); // 更新组件版本
// 核心组件版本不同,Windows Containers 基底映像 (Base Image) 的相容性不同。
// 更新組建版本不同,不影響 Windows Containers 執行,只差在安全性與功能修正而已,不牽涉核心調整。
// Ref https://blog.miniasp.com/post/2019/04/02/Understanding-Windows-OS-versioning
}
// GetVersionEx
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
printf("GetVersionEx: Version is %d.%d (%d:%s)\n",
osvi.dwMajorVersion, // 主版本
osvi.dwMinorVersion, // 次版本
osvi.dwBuildNumber, // 核心组件版本
osvi.szCSDVersion); // Service Pack
// Build Number在注册表中拿到信息可能不正确
// RtlGetVersionPtr
RTL_OSVERSIONINFOEXW osInfo = GetRealOSVersion();
if (osInfo.dwOSVersionInfoSize != 0)
{
if (wcscmp(osInfo.szCSDVersion, L"") == 0)
printf("RtlGetVersionPtr: Version is %d.%d (%d)\n",
osInfo.dwMajorVersion, // 主版本
osInfo.dwMinorVersion, // 次版本
osInfo.dwBuildNumber); // 核心组件版本
else
printf("RtlGetVersionPtr: Version is %d.%d (%d:%ws)\n",
osInfo.dwMajorVersion, // 主版本
osInfo.dwMinorVersion, // 次版本
osInfo.dwBuildNumber, // 核心组件版本
osInfo.szCSDVersion); // Service Pack
// OS Version
int currentBuildNumber = osInfo.dwBuildNumber;
std::map<int, std::string> windowsVersions = WindowsVersions::getWindowsVersions();
auto it = windowsVersions.find(currentBuildNumber);
if (it != windowsVersions.end()) {
printf("Windows Version: %s\n", it->second.c_str());
}
}
// 关闭注册表项
RegCloseKey(hKey);
getchar();
return 0;
}