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进行交互的查询语言。

  • 查询分析器下载:https://download.csdn.net/download/lyshark_csdn/87950095

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);// 将获取到的数据返回给OutBufwcstombs(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;
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/190176.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

若依中脱敏

SpringBoot使用自定义注解实现返回数据脱敏操作 在实际项目中&#xff0c;对于敏感数据的保护十分重要&#xff0c;数据脱敏又称数据去隐私化或数据变形&#xff0c;是在给定的规则、策略下对敏感数据进行变换、修改的技术机制&#xff0c;能够在很大程度上解决敏感数据在非可…

Redis(消息队列Stream)

Stream是一个轻量级的消息队列。 Redis中Stream的作用是提供一种高效的消息传递机制&#xff0c;允许多个消费者并行地消费消息&#xff0c;并且不会重复消费已经处理过的消息。它可以用于实现分布式任务队列、日志收集、实时数据处理等场景。Redis中的Stream支持多个消费者组…

医院绩效考核系统源码 医院绩效考核系统方案

医院绩效考核系统源码 医院绩效考核系统是现代医院管理的重要方法和科学的管理工具。良好的绩效管理&#xff0c;有助于带动全院职工的工作积极性&#xff0c;有助于提高工作效率、提高医疗质量、改善服务水平、降低运营成本&#xff0c;全面提升医院的精细化管理水平。 医院绩…

Springboot+vue的学生成绩管理系统(有报告),Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的学生成绩管理系统&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家…

ToolJet:开源低代码框架,轻松构建复杂可响应界面 | 开源日报 No.78

ToolJet/ToolJet Stars: 25.0k License: AGPL-3.0 ToolJet 是一个开源的低代码框架&#xff0c;可以通过最小化工程投入来构建和部署内部工具。ToolJet 的拖放式前端构建器允许您在几分钟内创建复杂、响应式的前端界面。此外&#xff0c;您还可以集成各种数据源&#xff0c;包…

「Verilog学习笔记」数据选择器实现逻辑电路

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 将变量A、B接入4选1数据选择器选择输入端S0 S1。将变量C分配在数据输入端。从表中可以看出输出L与变量C的关系。 当AB00时选通D0而此时L0&#xff0c;所以数据端D0接0…

计算机视觉的应用18-一键抠图人像与更换背景的项目应用,可扩展批量抠图与背景替换

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉的应用18-一键抠图人像与更换背景的项目应用&#xff0c;可扩展批量抠图与背景替换。该项目能够让你轻松地处理和编辑图片。这个项目的核心功能是一键抠图和更换背景。这个项目能够自动识别图片中的主体&…

SHELL中的循环语句

快捷查看指令 ctrlf 进行搜索会直接定位到需要的知识点和命令讲解&#xff08;如有不正确的地方欢迎各位小伙伴在评论区提意见&#xff0c;博主会及时修改&#xff09; 循环结构 连续出现的功能性代码 shell循环有四种: while 条件成立,循环就开始 直到循环条件不满足或者跳出…

vite vue3安装element-plus

准备 参考 安装 官网 yarn add element-plus完整引入 如果你对打包后的文件大小不是很在乎&#xff0c;那么使用完整导入会更方便。 main.ts // main.ts import { createApp } from vue import ElementPlus from element-plus import element-plus/dist/index.css import…

OpenCV C++ 图像处理实战 ——《OCR字符识别》

OpenCV C++ 图像处理实战 ——《OCR字符识别》 一、结果演示二、tesseract库配置2.1下载编译三、OCR字符识别3.1 文本检测方式3.1.1 RIL_BLOCK3.1.2 RIL_PARA3.1.3 RIL_TEXTLINE3.1.4 RIL_WORD3.1.5 RIL_SYMBOL3.2 英文文本检测3.3 中英文本检测四、源码测试图像下载总结一、结…

LLM大模型量化原理

大型语言模型&#xff08;LLM&#xff09;可以用于文本生成、翻译、问答任务等。但是&#xff0c;LLM 也非常大&#xff08;显然&#xff0c;大型语言模型&#xff09;并且需要大量内存。 这对于手机和平板电脑等小型设备来说可能具有挑战性。 可以将参数乘以所选的精度大小以…

Python接口自动化测试之token参数关联!

前言 在做自动化接口测试时&#xff0c;有时候会遇到token的动态关联&#xff0c;例如查询余额接口&#xff0c;需要关联登录接口的token动态值&#xff0c;如何利用python脚本进行接口token关联呢?今天我们爱学习一下吧&#xff01; 一&#xff1a;获取登录接口返回的token…