【Windows】使用 WMI 获取系统版本信息

发布于:2024-09-18 ⋅ 阅读:(174) ⋅ 点赞:(0)

获取系统版本信息

通过 RtlGetNtVersionNumbers 获取系统版本的方法可能不适用于所有情况,而且将要过时(被废弃)。下面介绍一种通过 WMI 查询并根据版本号进行划分的系统版本解析工具,其他方法还有通过注册表和通过文件属性等等。内部版本号表可以通过官方渠道获取,例如:
Windows 10 更新历史记录
Windows 11 更新历史记录

代码

sysinfo.h

#pragma once
#include <string>
#include <iostream>
#include <windows.h>
#include <iphlpapi.h>
#include <comdef.h>
#include <Wbemidl.h>
#include <math.h>

class SysInfo
{
public:
    SysInfo();
    virtual ~SysInfo();

    bool init_wmi();
    void uninit_wmi();


    double get_memory_size();
    std::string get_os_name();
    std::string get_host_name();
    int get_file_flag(std::string file_name);
    std::string get_area(std::string ip);
    std::string wstring_to_string(wchar_t* data);


protected:
private:
    bool m_init_wmi = false;

    IWbemServices* pSvc = NULL;
    IWbemLocator* pLoc = NULL;

    HRESULT hres = NULL;
};

SysInfo.cpp

#include "SysInfo.h"

#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "iphlpapi.lib")

#define  GBYTES  1073741824
#define  MBYTES  1048576
#define  KBYTES  1024
#define  DKBYTES 1024.0

SysInfo::SysInfo()
{
    m_init_wmi = init_wmi();
}

SysInfo::~SysInfo()
{
    uninit_wmi();
}

bool SysInfo::init_wmi()
{

    hres = CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hres))
    {
        return false;
    }

    hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    if (FAILED(hres))
    {
        CoUninitialize();
        return false;
    }


    hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
    if (FAILED(hres))
    {
        CoUninitialize();
        return false;
    }


    hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
    if (FAILED(hres))
    {
        pLoc->Release();
        CoUninitialize();
        return false;
    }

    hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
    if (FAILED(hres))
    {
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return false;
    }
    return true;
}

void SysInfo::uninit_wmi()
{

    pSvc->Release();
    pLoc->Release();
    CoUninitialize();
}


//Win32_PhysicalMemory

double SysInfo::get_memory_size()
{

    double mem_size = 0;

    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_PhysicalMemory")
        , WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
    if (FAILED(hres))
    {
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return -1;
    }

    IWbemClassObject* pclsObj = NULL;
    ULONG uReturn = 0;
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
        if (0 == uReturn)
        {
            break;
        }

        VARIANT vtProp = { 0 };
        VariantInit(&vtProp);// 标准初始化
        hr = pclsObj->Get(L"Capacity", 0, &vtProp, 0, 0);



        std::string data = wstring_to_string(vtProp.bstrVal);

        mem_size += ::atof(data.c_str());
        VariantClear(&vtProp);
        pclsObj->Release();
    }
    pEnumerator->Release();

    double mem_total = mem_size / 1024 / 1024 / 1024;

    return floor(mem_total * 100) / 100;
}



std::string SysInfo::get_os_name()
{
    std::string res_data;
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM win32_operatingsystem")
        , WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
    if (FAILED(hres))
    {
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return res_data;
    }

    IWbemClassObject* pclsObj = NULL;
    ULONG uReturn = 0;
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
        if (0 == uReturn)
        {
            break;
        }

        VARIANT vtProp = { 0 };
        VariantInit(&vtProp);// 标准初始化
        hr = pclsObj->Get(L"name", 0, &vtProp, 0, 0);
        std::string data = wstring_to_string(vtProp.bstrVal);
        data = data.substr(0, data.find('|'));

        hr = pclsObj->Get(L"Version", 0, &vtProp, 0, 0);
        res_data = wstring_to_string(vtProp.bstrVal);
        std::string restp = res_data;
        std::string temp = "[";
        temp += res_data;
        temp += "] ";
        temp += data;
        res_data = temp;

        // 分割string字符串
        int pos1 = 0, pos2 = 0;
        std::string pattern = ".";
        restp += pattern;
        std::string s[3];
        for (int i = 0; i < 3; i++) {
            pos2 = (int)restp.find(pattern, pos1);
            s[i] = restp.substr(pos1, 
                static_cast<std::basic_string<char, std::char_traits<char>, 
                std::allocator<char>>::size_type>(pos2) - pos1);
            pos1 = pos2 + 1;
        }
        //for (int i = 0; i < 3; i++) {
            //std::cout << s[i] << std::endl;
        //}
        /*
        size_t size = s[0].length() + 1;
        char* MajorVer = (char*)malloc(sizeof(char) * size);
        if (MajorVer != NULL) strcpy_s(MajorVer, size, s[0].c_str());

        size = s[1].length() + 1;
        char* MinorVer = (char*)malloc(sizeof(char) * size);
        if (MinorVer != NULL) strcpy_s(MinorVer, size, s[1].c_str());

        size = s[2].length() + 1;
        char* BuildVer = (char*)malloc(sizeof(char) * size);
        if (BuildVer != NULL) strcpy_s(BuildVer, size, s[2].c_str());
        */

        int MajorVer = 0, MinorVer = 0, BuildVer = 0, L;
        L = sscanf_s(s[0].c_str(), "%d", &MajorVer);
        L = sscanf_s(s[1].c_str(), "%d", &MinorVer);
        L = sscanf_s(s[2].c_str(), "%d", &BuildVer);

        printf("大版本号:%d, 小版本号:%d, 内部版本号:%d\n", MajorVer, MinorVer, BuildVer);

        printf("显式版本: ");
        if (BuildVer >= 22621) printf("Windows 11 22H2 Or Greater\n");
        else if (BuildVer >= 22000) printf("Windows 11 21H2\n");
        else if (BuildVer == 20348) printf("Windows Server 2022\n");
        else if (BuildVer >= 19045) printf("Windows 10 22H2\n");
        else if (BuildVer >= 19044) printf("Windows 10 21H2\n");
        else if (BuildVer >= 19043) printf("Windows 10 21H1\n");
        else if (BuildVer >= 19042) printf("Windows 10 20H2\n");
        else if (BuildVer >= 19041) printf("Windows 10 2004\n");
        else if (BuildVer >= 18363) printf("Windows 10 1909\n");
        else if (BuildVer >= 18362) printf("Windows 10 1903\n");
        else if (BuildVer >= 17763) printf("Windows 10 1809\n");
        else if (BuildVer >= 17134) printf("Windows 10 1803\n");
        else if (BuildVer >= 16299) printf("Windows 10 1709\n");
        else if (BuildVer >= 15063) printf("Windows 10 1703\n");
        else if (BuildVer >= 14393) printf("Windows 10 1607\n");
        else if (BuildVer >= 10586) printf("Windows 10 1511\n");
        else if (BuildVer >= 10240) printf("Windows 10 1507\n");
        // 以下数据属于网络收集,不一定准确,数据已经不可考究
        else if (BuildVer >= 9200)
        {// 6.2->win 8; 6.3->win 8.1
            if (MinorVer == 2) printf("Windows 8 Release\n");
            else if (MinorVer == 3) printf("Windows 8.1 Release\n");
        }
        else if (BuildVer >= 7601) printf("Windows 7 Service Pack 1\n");
        else if (BuildVer >= 7600) printf("Windows 7 Release\n");
        else if (BuildVer >= 6002) printf("Windows Vista SP2\n");
        else if (BuildVer >= 6001) printf("Windows Vista SP1\n");
        else if (BuildVer >= 6000) printf("Windows Vista\n");
        else if (BuildVer >= 3790) printf("Windows XP Professional x64 Edition\n");
        else if (BuildVer == 3000) printf("Windows Me");// 版本特殊?
        else if (BuildVer >= 2600) printf("Windows XP\n");// 存在特殊版本
        else if (BuildVer == 2222) printf("Windows 98 Second Edition\n");// 版本特殊?
        else if (BuildVer >= 2195) printf("Windows 2000 Professional\n");
        else if (BuildVer >= 1998) printf("Windows 98\n");
        else if (BuildVer >= 1381) printf("Windows NT Workstation 4.0\n");
        else if (BuildVer >= 1057) printf("Windows NT Workstation 3.51\n");// 版本特殊?
        else if (BuildVer >= 950) printf("Windows 95\n");
        else if (BuildVer >= 807) printf("Windows NT Workstation 3.5\n");
        else if (BuildVer >= 528) printf("Windows NT 3.1\n");
        else printf("版本特殊或者为远古版本!\n");



        // 释放
        //free(MajorVer);
        //free(MinorVer);
        //free(BuildVer);
        VariantClear(&vtProp);
        pclsObj->Release();
    }
    pEnumerator->Release();

    return res_data;

}




std::string SysInfo::get_host_name()
{
    std::string host_name;

    char buf[MAX_PATH] = { 0 };
    DWORD length = MAX_PATH;
    if (::GetComputerNameA(buf, &length)) {
        host_name = buf;
    }
    return host_name;
}


int SysInfo::get_file_flag(std::string file_name)
{
    return 0;
}

std::string SysInfo::get_area(std::string ip)
{
    std::string area;

    return area;
}

std::string SysInfo::wstring_to_string(wchar_t* data)
{
    std::string res_data;
    int iSize;
    // 宽字符串转换
    iSize = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL);
    char* pCapacity = (char*)malloc(iSize * sizeof(char));
    if (pCapacity == NULL) return res_data;
    pCapacity[0] = 0;
    WideCharToMultiByte(CP_ACP, 0, data, -1, pCapacity, iSize, NULL, NULL);
    res_data = pCapacity;
    free(pCapacity);
    return res_data;
}

mian.cpp

#include "SysInfo.h"

int main()
{

	SysInfo Info;
	Info.init_wmi();
	printf("%s\n", Info.get_os_name().c_str());
	//Info.uninit_wmi();
	system("pause");
	return 0;
}

效果如图所示:
在这里插入图片描述
代码是很早之前写的,用的话需要自己优化一下。


原文出处链接:https://blog.csdn.net/qq_59075481/article/details/142319803
本文发布于:2024.09.17,修改于:2024.09.17。


网站公告

今日签到

点亮在社区的每一天
去签到