C/C++ 中运用WMI接口查询系统各类信息,如软件信息、磁盘信息...

发布时间 2023-12-26 07:54:08作者: 架构师老卢

 

在C/C++中使用WMI(Windows Management Instrumentation)接口查询系统信息是一种强大的方法。下面是一个简单的例子,演示如何使用WMI查询系统信息,包括安装的软件信息、磁盘信息、网络适配器信息、操作系统信息等。请注意,这里使用的是COM接口,因此需要在代码中进行COM的初始化和反初始化。

#include <Windows.h>
#include <iostream>
#include <comdef.h>
#include <Wbemidl.h>

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

void QueryWMI(const wchar_t* query)
{
    // 初始化COM
    HRESULT hres = CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hres))
    {
        std::wcerr << L"Failed to initialize COM library. Error code = 0x" << std::hex << hres << std::endl;
        return;
    }

    // 初始化COM安全性
    hres = CoInitializeSecurity(
        nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE, nullptr);

    if (FAILED(hres))
    {
        std::wcerr << L"Failed to initialize security. Error code = 0x" << std::hex << hres << std::endl;
        CoUninitialize();
        return;
    }

    // 创建WMI实例
    IWbemLocator* pLoc = nullptr;
    hres = CoCreateInstance(
        CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast<LPVOID*>(&pLoc));

    if (FAILED(hres))
    {
        std::wcerr << L"Failed to create IWbemLocator object. Error code = 0x" << std::hex << hres << std::endl;
        CoUninitialize();
        return;
    }

    // 连接到WMI
    IWbemServices* pSvc = nullptr;
    hres = pLoc->ConnectServer(
        _bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, 0, nullptr, 0, 0, &pSvc);

    if (FAILED(hres))
    {
        std::wcerr << L"Failed to connect to ROOT\\CIMV2. Error code = 0x" << std::hex << hres << std::endl;
        pLoc->Release();
        CoUninitialize();
        return;
    }

    // 设置安全级别
    hres = CoSetProxyBlanket(
        pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE);

    if (FAILED(hres))
    {
        std::wcerr << L"Failed to set proxy blanket. Error code = 0x" << std::hex << hres << std::endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return;
    }

    // 执行WMI查询
    IEnumWbemClassObject* pEnumerator = nullptr;
    hres = pSvc->ExecQuery(
        _bstr_t(L"WQL"), _bstr_t(query), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, &pEnumerator);

    if (FAILED(hres))
    {
        std::wcerr << L"Query for data failed. Error code = 0x" << std::hex << hres << std::endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return;
    }

    // 枚举查询结果
    IWbemClassObject* pclsObj = nullptr;
    ULONG uReturn = 0;

    while (pEnumerator)
    {
        hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

        if (uReturn == 0)
            break;

        VARIANT vtProp;

        // 获取属性值
        hres = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);

        if (SUCCEEDED(hres))
        {
            std::wcout << L"Name : " << vtProp.bstrVal << std::endl;
            VariantClear(&vtProp);
        }

        pclsObj->Release();
    }

    // 释放资源
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();
}

int main()
{
    // 查询所有已安装的软件
    QueryWMI(L"SELECT * FROM Win32_Product");

    // 查询磁盘信息
    QueryWMI(L"SELECT * FROM Win32_DiskDrive");

    // 查询网络适配器信息
    QueryWMI(L"SELECT * FROM Win32_NetworkAdapter");

    // 查询操作系统信息
    QueryWMI(L"SELECT * FROM Win32_OperatingSystem");

    // 查询正在运行的进程信息
    QueryWMI(L"SELECT * FROM Win32_Process");

    // 查询所有用户账户信息
    QueryWMI(L"SELECT * FROM Win32_UserAccount");

    // 查询系统启动项信息
    QueryWMI(L"SELECT * FROM Win32_StartupCommand");

    // 查询物理内存信息
    QueryWMI(L"SELECT * FROM Win32_PhysicalMemory");

    return 0;
}

这只是一个简单的例子,你可能需要根据自己的需求修改查询语句和处理结果的方式。此外,确保在使用WMI之前充分了解WMI的概念和相应的类。