C/C++运用WMI接口实现查询系统信息

 更新时间:2023年11月18日 16:04:05   作者:lyshark  
Windows Management Instrumentation(WMI)是一种用于管理和监视Windows操作系统的框架,本文主要介绍了如何运用WMI接口实现查询系统信息,感兴趣的可以了解下

Windows Management Instrumentation(WMI)是一种用于管理和监视Windows操作系统的框架。它为开发人员、系统管理员和自动化工具提供了一种标准的接口,通过这个接口,可以获取有关计算机系统硬件、操作系统和应用程序的信息,以及对系统进行管理和控制的能力。

WMI允许通过编程方式查询系统信息、监视性能、执行管理任务等。它提供了一种统一的方式来访问和管理Windows操作系统的各个方面,而无需了解底层实现细节。通过WMI,可以使用各种编程语言(如C#、VBScript、PowerShell等)来执行诸如查询系统信息、监控性能、配置系统设置等任务。

当需要通过WMI编程提取参数时,我们就需要使用WQL(Windows Management Instrumentation Query Language)它是一种查询语言,专门用于查询Windows Management Instrumentation (WMI)数据。WMI 是Windows操作系统中用于管理和监视的框架,而WQL则是用于与WMI进行交互的查询语言。

WQL 的语法类似于 SQL(Structured Query Language),使用WQL可以执行各种查询来检索关于计算机系统、硬件、软件和其他管理信息的数据。这些查询可以用于编写脚本、管理任务、监视性能等。为了方便查询获取参数这里提供一个简单的查询工具供大家查询使用,下载后打开,其默认查询的是Win32_ComputerSystem也就是系统的基本参数信息;

如果我们需要获取其他信息,比如得到计算机中所安装的所有Windows服务信息,可以执行SELECT * FROM Win32_Service语句,当然也有许多其他的通用语句可以让我们使用,例如如下几种常用的语句。

查询所有安装的软件

SELECT * FROM Win32_Product

查询所有逻辑磁盘的信息

SELECT * FROM Win32_LogicalDisk

查询所有网络适配器的信息

SELECT * FROM Win32_NetworkAdapter

查询操作系统信息

SELECT * FROM Win32_OperatingSystem

查询所有正在运行的进程

SELECT * FROM Win32_Process

查询所有用户账户信息

SELECT * FROM Win32_UserAccount

查询系统启动项

SELECT * FROM Win32_StartupCommand

查询物理内存

SELECT * FROM Win32_PhysicalMemory

如上图所示,查询将返回Win32_Service类中所有服务的信息。你可以根据需要编写更复杂的查询,以满足特定的管理或监视要求。

为了让读者更加方便的使用查询功能,此处我封装了一个SelectQuerySQL查询函数,该函数需要传入特定的查询语句,特定的查询字段以及返回值缓冲区,此时只需要读取缓冲区内的数据即可得到查询结果。

#define _CRT_SECURE_NO_WARNINGS
#define _WIN32_DCOM
#define _CRT_NONSTDC_NO_DEPRECATE

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

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

using namespace std;

// 去掉字符串中的空格
void Trims(char* data)
{
    int i = -1, j = 0;
    int ch = ' ';

    while (data[++i] != '\0')
    {
        if (data[i] != ch)
        {
            data[j++] = data[i];
        }
    }
    data[j] = '\0';
}

// 通用查询方法,每次查询一条
bool SelectQuerySQL(LPCWSTR SQL, LPCWSTR Key, OUT char OutBuf[1024])
{
    HRESULT hres;

    CoUninitialize();
    hres = CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hres))
    {
        return false;
    }
    hres = CoInitializeSecurity(0, -1, 0, 0, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, 0, EOAC_NONE, 0);
    if (FAILED(hres))
    {
        CoUninitialize();
        return false;
    }
    IWbemLocator* pLoc = NULL;
    hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
    if (FAILED(hres))
    {
        CoUninitialize();
        return false;
    }
    IWbemServices* pSvc = NULL;
    hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), 0, 0, 0, 0, 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;
    }

    IEnumWbemClassObject* pEnumerator = NULL;

    // 执行WSQL语句
    hres = pSvc->ExecQuery(bstr_t("WQL"),bstr_t(SQL),WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,NULL,&pEnumerator);
    if (FAILED(hres))
    {
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return false;
    }
    IWbemClassObject* pclsObj;
    ULONG uReturn = 0;
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
        if (0 == uReturn)
        {
            break;
        }
        VARIANT vtProp;

        // 获取到指定Key字段
        hr = pclsObj->Get(Key, 0, &vtProp, 0, 0);

        // 将获取到的数据返回给OutBuf
        wcstombs(OutBuf, vtProp.bstrVal, 1024);
        VariantClear(&vtProp);
        pclsObj->Release();
    }
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();
    return true;
}

有了上述函数的封装,那么实现查询就变得很容易了,当我们需要查询CPU序列号时,可以直接执行SELECT * FROM win32_Processor并取出里面的ProcessorId字段,使用函数时可以总结为如下所示的案例;

int main(int argc, char *argv[])
{
	char RefBuffer[1024] = { 0 };
	bool ref = false;

	ref = SelectQuerySQL(L"SELECT * FROM win32_Processor", L"ProcessorId", RefBuffer);
	std::cout << "获取CPU序列号: " << RefBuffer << std::endl;
	Trims(RefBuffer);

	system("pause");
	return 0;
}

输出效果如下所示;

根据这个查询方法,我们就可以得到系统的各类固件序列号,这对于软件认证尤为重要;

int main(int argc, char *argv[])
{
	char RefBuffer[1024] = { 0 };
	bool ref = false;

	ref = SelectQuerySQL(L"SELECT * FROM win32_Processor", L"ProcessorId", RefBuffer);
	std::cout << "获取CPU序列号: " << RefBuffer << std::endl;
	Trims(RefBuffer);

	ref = SelectQuerySQL(L"SELECT * FROM Win32_BaseBoard", L"SerialNumber", RefBuffer);
	std::cout << "获取主板ID号: " << RefBuffer << std::endl;
	Trims(RefBuffer);

	ref = SelectQuerySQL(L"SELECT * FROM Win32_BIOS", L"SerialNumber", RefBuffer);
	std::cout << "获取BIOS序列号: " << RefBuffer << std::endl;
	Trims(RefBuffer);

	ref = SelectQuerySQL(L"SELECT * FROM Win32_PhysicalMemory", L"SerialNumber", RefBuffer);
	std::cout << "获取内存序列号: " << RefBuffer << std::endl;
	Trims(RefBuffer);

	ref = SelectQuerySQL(L"SELECT * FROM Win32_DiskDrive WHERE Index = 0", L"SerialNumber", RefBuffer);
	Trims(RefBuffer);
	std::cout << "获取硬盘序列号: " << RefBuffer << std::endl;

	system("pause");
	return 0;
}

输出效果如下所示;

当然,有时我们也需要一次性输出多个参数,某些数据存在多条记录,在输出时也需要增加一些代码,我们以Win32_LogicalDisk为例,代码需要进行一定的改进,在循环时分别取出不同的字段,此时的查询函数需要相应的做一些改进,如下是查询函数需要变化的位置。

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

    // 输出盘符字段
    VARIANT vtProp_DeviceID;
    VARIANT vtProp_FreeSpace;
    VARIANT vtProp_Size;

    // 获取到指定Key字段
    hr = pclsObj->Get(L"DeviceID", 0, &vtProp_DeviceID, 0, 0);
    hr = pclsObj->Get(L"FreeSpace", 0, &vtProp_FreeSpace, 0, 0);
    hr = pclsObj->Get(L"Size", 0, &vtProp_Size, 0, 0);

    // 转换数据为字符串
    char x[32], y[32], z[32];
    wcstombs(x, vtProp_DeviceID.bstrVal, 32);
    wcstombs(y, vtProp_FreeSpace.bstrVal, 32);
    wcstombs(z, vtProp_Size.bstrVal, 32);

    std::cout << "分区: " << x << std::endl;
    std::cout << "剩余: " << y << std::endl;
    std::cout << "容量: " << z << std::endl;

    // 清理
    VariantClear(&vtProp_DeviceID);
    VariantClear(&vtProp_FreeSpace);
    VariantClear(&vtProp_Size);
    pclsObj->Release();
}

此外,在查询参数上也应该修改为对应的SELECT * FROM Win32_LogicalDisk查询磁盘;

int main(int argc, char *argv[])
{
	char RefBuffer[1024] = { 0 };
	bool ref = false;

	ref = SelectQuerySQL(L"SELECT * FROM Win32_LogicalDisk", L"ProcessorId", RefBuffer);
	Trims(RefBuffer);

	system("pause");
	return 0;
}

此时,当再一次运行这段代码,就可以查询到当前系统中所有的磁盘信息,如下图所示;

以上就是C/C++运用WMI接口实现查询系统信息的详细内容,更多关于C++ WMI查询系统信息的资料请关注脚本之家其它相关文章!

相关文章

  • C++实现景区旅游信息管理系统

    C++实现景区旅游信息管理系统

    这篇文章主要为大家详细介绍了C++实现景区旅游信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++ move semantic移动语义介绍

    C++ move semantic移动语义介绍

    首先,移动语义和完美转发这两个概念是在C++的模板编程的基础上,新增的特性,主要是配合模板来使用。本篇会从C++的值类型,到移动拷贝与移动赋值来理解移动语义与完美转发
    2022-08-08
  • c语言 两字符串交叉合并实例

    c语言 两字符串交叉合并实例

    今天小编就为大家分享一篇c语言 两字符串交叉合并实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • C++ Qt实现一个解除文件占用小工具

    C++ Qt实现一个解除文件占用小工具

    这篇文章主要为大家详细介绍了如何利用C++ Qt实现一个解除文件占用小工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-09-09
  • C++浅拷贝与深拷贝及引用计数分析

    C++浅拷贝与深拷贝及引用计数分析

    这篇文章主要介绍了C++浅拷贝与深拷贝及引用计数分析的相关资料,需要的朋友可以参考下
    2017-06-06
  • C++实现扫雷小游戏

    C++实现扫雷小游戏

    这篇文章主要为大家详细介绍了C++实现扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • C++将音频PCM数据封装成wav文件的方法

    C++将音频PCM数据封装成wav文件的方法

    这篇文章主要为大家详细介绍了C++将音频PCM数据封装成wav文件的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C++文件相关函数CreateFile|ReadFile|WriteFile用法详解

    C++文件相关函数CreateFile|ReadFile|WriteFile用法详解

    这篇文章主要为大家详细介绍了c++有关文件创建、读取和写入的api:CreateFile、ReadFile、WriteFile的具体使用,需要的可以参考下
    2023-04-04
  • 关于C语言位运算的简单示例

    关于C语言位运算的简单示例

    这篇文章主要介绍了关于C语言位运算的简单示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • C语言堆与二叉树的顺序结构与实现

    C语言堆与二叉树的顺序结构与实现

    堆是计算机科学中一类特殊的数据结构的统称,通常是一个可以被看做一棵完全二叉树的数组对象。而堆排序是利用堆这种数据结构所设计的一种排序算法。本文将详细介绍堆与二叉树的顺序结构与实现,需要的可以参考一下
    2022-05-05

最新评论