C/C++ 运用VMI接口查询系统信息
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++ 运用VMI接口查询系统信息的更多相关文章
- 读取jar文件的sha1码,请求maven官方的solrsearch接口查询该jar文件所对应的maven坐标信息
版权声明:本文为博主原创文章,未经博主允许不得转载. import com.google.gson.JsonObject; import com.google.gson.JsonParser; imp ...
- DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render
DRF框架 全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...
- 通过IFeatureClass 接口查询 IWorkspace, 查询通配符
IWorkspace pWsI = ((IDataset)pFtCls).Workspace 查询通配符 ISQLSyntax psqls = (ISQLSyntax)(((IDataset)pFtC ...
- Linux查询系统信息命令
Linux查看系统信息是比较基础的知识,所以这个应该都需要掌握,命令和解释如下: #uname -a 查看操作系统.内核.CPU信息 #head -n 1 /etc/issue ...
- Oracle 通过数据字典查询系统信息
简介:数据字典记录了数据库系统的信息,他是只读表和视图的集合,数据字典的所有者是sys用户.注:用户只能在数据字典上执行查询操作,而维护和修改是由系统自己完成的. 1.数据字典的组成:数据字典包括数据 ...
- rails的接口查询详解
Retrieving Objects from the Database find "find"是一种常用的数据库查询方法,在Rails中被用于从数据库中查找单个记录.它可以接收一 ...
- 非常全的API接口查询
http://www.apix.cn/services/category/3 https://www.showapi.com/ https://www.juhe.cn/docs http://deve ...
- 手机号码归属地查询api接口
淘宝网 API地址: http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443 参数: tel:手机号码 返回:JSON ...
- 新浪网易淘宝等IP地区信息查询开放API接口调用方法
通过IP地址获取对应的地区信息通常有两种方法:1)自己写程序,解析IP对应的地区信息,需要数据库.2)根据第三方提供的API查询获取地区信息. 第一种方法,参见文本<通过纯真IP数据库获取IP地 ...
- ArcGIS Engine开发之旅08--和查询相关的对象和接口
原文:ArcGIS Engine开发之旅08--和查询相关的对象和接口 查询在GIS领域应该是一个很频繁的操作,在GIS中除了具有属性查询(和其他关系型数据库的查询类似),还提供了空间查询.在介绍查询 ...
随机推荐
- Flutter系列文章-Flutter进阶2
这一节我将再详细地为您介绍 Flutter 进阶主题,包括导航和路由.状态管理.异步处理.HTTP请求和Rest API,以及数据持久化.让我们逐个介绍这些主题. 1.导航和路由 在 Flutter ...
- protolator - Protobuf <==> json
github.com/hyperledger/fabric-config/protolator 是 Hyperledger Fabric 中的一个 Go 包,用于将 Protocol Buffers( ...
- 图解算法,原理逐步揭开「GitHub 热点速览」
想必每个面过大厂的小伙伴都被考过算法,那么有没有更快了解算法的方式呢?这是一个老项目,hello-algo 用图解的方式让你了解运行原理.此外,SQL 闯关自学项目也是一个让你能好好掌握 SQL 技术 ...
- C#程序的启动显示方案(无窗口进程发送消息) - 开源研究系列文章
今天继续研究C#的WinForm的实例显示效果. 我们上次介绍了Winform窗体的唯一实例运行代码(见博文:基于C#的应用程序单例唯一运行的完美解决方案 - 开源研究系列文章 ).这就有一个问题,程 ...
- 利用pytorch准备数据集、构建与训练、保存与加载CNN模型
本文的主要内容是利用pytorch框架与torchvision工具箱,进行准备数据集.构建CNN网络模型.训练模型.保存和加载自定义模型等工作.本文若有疏漏.需更正.改进的地方,望读者予以指正,如果本 ...
- 【pandas小技巧】--列值的映射
映射列值是指将一个列中的某些特定值映射为另外一些值,常用于数据清洗和转换. 使用映射列值的场景有很多,以下是几种常见的场景: 将字符串类型的列中的某些值映射为数字.例如,将"男"和 ...
- 老问题了:idea中使用maven archetype新建项目时卡住
背景 作为一个后端Java打工人,idea就是最重要的打饭工具.创建项目,熟悉吧,但是,这么多年下来,因为idea换了版本,电脑换了等等,我还是时不时遇到根据maven archetype新建mave ...
- 零代码,使用 Dify 和 Laf 两分钟接入企业微信 AI 机器人
Dify 允许创建 AI 应用,并提供二次开发的能力.这里我将演示创建一个法律问答助手的 AI 应用,称作"知法".在本篇教程中,我将指导你为"知法"接入企业微 ...
- ORM查询一个表中有两个字段相同时,只获取某个值最大的一条
Table表如下: 获取表中name和hex值相同时age最大的那一条 ORM写法,两次查询 ids = table.values('name', 'age').annotate(id=Max('id ...
- iFiles浏览iphone文件
我们希望能在iphone中浏览文件系统的目录