QT案例 使用WMI获取win_32类的属性值,包括Win32提供程序类中的属性

news2024/9/22 15:31:22

最近涉及到读取WINDOWS 系统电脑设备的各种信息,在一些特殊的PE或者简化系统中是没有WMI查询工具的,所以就自己写了个查询大部分WMI属性值的工具,免去了查网站的功夫。涉及到的方法内容就汇总做个总结。
PS:因为工作中软件基本都是我一个人开发和维护,所以一般就写一堆一个方法,最近看了很多 GitHub上的代码顿时有种写了一堆屎的感觉,啧啧,向诸位大佬学习借鉴

Win32提供程序查询主要代码

      • 初始化COM库
      • 获取IWbemServices实例
      • WQL查询
      • 获取属性名称、类型的另一种写法
      • CIMTYPE 数据类型转换
      • gumbo-parse解析HTML
      • 小工具可执行程序看文章附件资源
      • 源码下载

初始化COM库

void _print_hresult(const char *file, int line, const char *msg, HRESULT hr);
#define PRINT_HRESULT(hr, msg) _print_hresult(__FILE__, __LINE__, msg, hr)
#define IFFAILED_PRINTERROR(hr, msg)  { HRESULT __hr__ = (hr); if ((__hr__ != RPC_E_TOO_LATE) &&FAILED(__hr__)) { PRINT_HRESULT(__hr__, msg); } }

static class BLL_CUSTOM_LIBRARY_EXPORT COMThreading {
public:
    COMThreading() {
        // Regardless of return value, you must balance each call to
        // CoInitialize[Ex] with a call to CoUninitialize.
        HRESULT hres = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
        IFFAILED_PRINTERROR(hres, "Error on CoInitializeEx");
        hres =CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT,
                                               RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
         IFFAILED_PRINTERROR(hres, "Error on CoInitializeSecurity");
    }

    ~COMThreading() {
        CoUninitialize();
    }
};

这种初始化COM库的写法真的就很经典,完全不用担心调用后没释放的问题,第一次看到的时候真的觉得大佬真是牛逼。

获取IWbemServices实例

#define PRINT_HRESULT(hr, msg)   WMIOBJ_PRINT_ERROR(QString("%1 : %2").arg(msg).arg(GetError(hr)))
#define IFFAILED_PRINTERROR(hr, msg)  { HRESULT __hr__ = (hr); if ((__hr__ != RPC_E_TOO_LATE) &&FAILED(__hr__)) { PRINT_HRESULT(__hr__, msg); } }

HRESULT GetWMIProxy(const CString &objectPath, CComPtr<IWbemServices> &pSvc)
{
    WMIOBJ_PRINT_INFO("Execution GetWMIProxy...");

    HRESULT hres;
    CComPtr<IWbemLocator> pLoc;

    hres = CoInitializeSecurity(
                NULL,
                -1,                          // COM authentication
                NULL,                        // Authentication services
                NULL,                        // Reserved
                RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
                RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
                NULL,                        // Authentication info
                EOAC_NONE,                   // Additional capabilities
                NULL                         // Reserved
                );
    IFFAILED_PRINTERROR(hres, "Error on CoInitializeSecurity.");

    // Obtain the initial locator to WMI
    hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc);
    IFFAILED_RETURN_RES(hres, "Error on CoCreateInstance.");

    hres = pLoc->ConnectServer(
                _bstr_t(objectPath),     // Object path of WMI namespace
                NULL,                    // User name. NULL = current user
                NULL,                    // User password. NULL = current
                0,                       // Locale. NULL indicates current
                NULL,                    // Security flags.
                0,                       // Authority (for example, Kerberos)
                0,                       // Context object
                &pSvc                    // pointer to IWbemServices proxy
                );
    IFFAILED_RETURN_RES(hres, "Error on pLoc->ConnectServer.");

    // Set security levels on the proxy
    hres = CoSetProxyBlanket(
                pSvc,                        // Indicates the proxy to set
                RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
                RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
                NULL,                        // Server principal name
                RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
                RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
                NULL,                        // client identity
                EOAC_NONE                    // proxy capabilities
                );
    IFFAILED_RETURN_RES(hres, "Error on CoSetProxyBlanket.");

    return hres;
}

硬件方面的命名空间大多是 L"ROOT\CIMV2",宏定义可以这么用我是真的没想到,我以前还是用的简单了,

WQL查询

通过传人WQL查询对应类的所有属性,只做示例,对应参数类型是封装好的,获取返回参数的所有属性,也是有很多种方法。

   void Lib_WmiObject::SQL_WQL(QString WQL)
{
    QueryTitle title;
    QueryData Data;

    WMIOBJ_PRINT_INFO("Execution Select WQL...<b>START</b>");
    COMThreading();
    HRESULT hres;
    CComPtr<IWbemServices> pSvc;
    IFFAILED_RETURN(GetWMIProxy(WMI_NAMESPACE, pSvc), " Lib_WmiQuery : Couldn't get WMI proxy");


    WMIOBJ_PRINT_INFO("WQL : "+WQL);
    CComPtr<IEnumWbemClassObject> pEnumerator;
    hres = pSvc->ExecQuery(bstr_t(L"WQL"),
                           bstr_t(WQL.toStdWString().c_str()),
                           WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
                           NULL,
                           &pEnumerator);
    IFFAILED_RETURN(hres, "WQL ["+WQL+"] Execution failure.");

    if(!pEnumerator)
        WMIOBJ_PRINT_ERROR("WQL 执行失败:"+QString(GetError()));

    while (pEnumerator)
    {
        CComPtr<IWbemClassObject> pclsObj;
        ULONG uReturn = 0;
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
        if(0 == uReturn || pclsObj == NULL)
        {
            if(hr!=ERROR_INVALID_FUNCTION)
                WMIOBJ_PRINT_ERROR("WQL 执行失败:"+QString(GetError(hr)));
            break;
        }

        if(title.count()==0)
        {
            SAFEARRAY* pNames;
            hres=pclsObj->GetNames(L"",WBEM_FLAG_ALWAYS,NULL,&pNames);
            if (FAILED(hres))
            {
                WMIOBJ_PRINT_ERROR("获取属性名称列表失败!");
                break;
            }
            
            qDebug()<<"lLbound : "<<pNames->cDims;
            qDebug()<<"cbElements : "<<pNames->cbElements;
            BSTR HUGEP *pbstr;
            // Get a pointer to the elements of the array.
            hr = SafeArrayAccessData(pNames, (void HUGEP**)&pbstr);
            if (FAILED(hr))
                continue;
            for (int i = 0; i < pNames->rgsabound->cElements; i++)
            {
                BSTR bstrTemp = pbstr[i];
                title.append(QString::fromWCharArray(bstrTemp));
            }
            SafeArrayDestroy(pNames);


        }

        QStringList _Data;
        foreach (QString name , title) {
            VARIANT vtProp;
            CIMTYPE  pType= CIM_EMPTY;
            VariantInit(&vtProp);
            hr = pclsObj->Get(name.toStdWString().c_str(), 0, &vtProp, &pType, 0);
            if(FAILED(hr))
            {
                _Data.append("[ERROR]");
            }
            else
                _Data.append(check_vatiant_type(vtProp,pType));
            VariantClear(&vtProp);
        }
        Data.append(_Data);
    }

    UnCOMThreading();
    WMIOBJ_PRINT_INFO("Execution Select WQL...<b>END</b>");
    emit Out_Data(title,Data);
}

获取属性名称、类型的另一种写法

#define IFFAILED_RETURN_RES2(hr, msg)        { HRESULT __hr__ = (hr); if (FAILED(__hr__)) { PRINT_HRESULT(__hr__, msg); return __hr__; } }
HRESULT EnumerateProperties(IWbemClassObject * pObject)
{
    BSTR name;
    VARIANT val;
    CIMTYPE type;
    LONG flavor;

    IFFAILED_RETURN_RES2(pObject->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY), "BeginEnumeration");

    qDebug("Properties:");
    while (pObject->Next(0, &name, &val, &type, &flavor) != WBEM_S_NO_MORE_DATA) {
        qDebug("%-20ls type=0x%04x val.vt=0x%04x val:%s", name, type, val.vt,check_vatiant_type(val,type).toStdString().c_str());
        SysFreeString(name);
        VariantClear(&val);
    }

    return S_OK;
}

CIMTYPE 数据类型转换

之前在GitHub上看到过一个VARIANT数据类型转换的,结果忘了保存下来,自己又不想写,GitHub又打不开,所以只有用CIMTYPE 类型转换成QString

QString Lib_WmiObject::check_vatiant_type(VARIANT Value,CIMTYPE _enum_type)
{
    if(Value.vt==VT_NULL)
        return "[NULL]";

    switch ( _enum_type ){
    case CIM_ILLEGAL ://值: 0xfff非法值。
        return QString::fromWCharArray(Value.bstrVal);
    case CIM_EMPTY : //值: 0 空 (null) 值。
        return "[NULL]";
    case CIM_SINT8 : //值: 16//8 位有符号整数。
        return  QString::number(Value.iVal);
    case CIM_SINT16 : //值: 2//16 位带符号整数。
        return  QString::number(Value.iVal);
    case CIM_SINT32 : //值: 3//32 位带符号整数。
        return  QString::number(Value.intVal);
    case CIM_SINT64 : //值: 20//64 位带符号整数。
        return  QString::number(Value.llVal,10);
    case CIM_UINT8 : //值: 17//8 位无符号整数。
        return  QString::number(Value.uiVal);
    case CIM_UINT16 : //值: 18//16 位无符号整数。
        return  QString::number(Value.uintVal);
    case CIM_UINT32 : //值: 19//32 位无符号整数。
        return  QString::number(Value.uintVal);
    case CIM_UINT64 : //值: 21//64 位无符号整数。
        return  QString::number(Value.ullVal,10);
    case CIM_REAL32 : //值: 4//32 位实数。
        return  QString::number(Value.intVal);
    case CIM_REAL64 : //值: 5//64 位实数。
        return  QString::number(Value.ullVal,10);
    case CIM_BOOLEAN : //值: 11//一个布尔值。
        return Value.boolVal?"TRUE":"FALSE";
    case CIM_STRING : // 值: 8// 字符串值。
        return QString::fromWCharArray(Value.bstrVal);
    case CIM_DATETIME : //值: 101//一个日期时间值。
    case CIM_REFERENCE : //值: 102//另一个对象的引用 (__Path) 。
    case CIM_CHAR16 : //值: 103//16 位字符值。
    case CIM_OBJECT : //值: 13//Object 值 。
    case CIM_FLAG_ARRAY : // 值: 0x2000//数组值。
        return QString::fromWCharArray(Value.bstrVal);
    default:
        return QString::fromWCharArray(Value.bstrVal);
    }
}

gumbo-parse解析HTML

gumbo-parse用来解析html还行。不确定是不是我方法没写对,我之前尝试过用gumbo-parse解析XML,获取不到节点,最后还是用的QT自带的XML解析工具。

 * https://blog.csdn.net/chijingjing/article/details/104255763

#pragma once
#include "stdafx.h"

#include "enumtest.cpp"

#include "gumbo-parser/Selector.h"

#include "gumbo-parser/Document.h"
#include "gumbo-parser/Selection.h"
#include "gumbo-parser/Node.h"

void test_parser() {
    std::string page("<h1><a>wrong link</a><a class=\"special\"\\>some link</a></h1>");
    CDocument doc;
    doc.parse(page.c_str());

    CSelection c = doc.find("h1 a.special");
    CNode node = c.nodeAt(0);
    printf("Node: %s\n", node.text().c_str());
    std::string content = page.substr(node.startPos(), node.endPos() - node.startPos());
    printf("Node: %s\n", content.c_str());

}

void test_html() {
    std::string page = "<html><div><span>1\n</span>2\n</div></html>";
    CDocument doc;
    doc.parse(page.c_str());
    CNode pNode = doc.find("div").nodeAt(0);
    std::string content = page.substr(pNode.startPos(), pNode.endPos() - pNode.startPos());
    printf("Node: #%s#\n", content.c_str());
}

void test_escape() {
    std::string page = "<html><div><span id=\"that's\">1\n</span>2\n</div></html>";
    CDocument doc;
    doc.parse(page.c_str());
    CNode pNode = doc.find("span[id=\"that's\"]").nodeAt(0);
    std::string content = page.substr(pNode.startPos(), pNode.endPos() - pNode.startPos());
    printf("Node: #%s#\n", content.c_str());
}

int main() {
    test_parser();
    test_html();
    test_escape();
}
————————————————
版权声明:本文为CSDN博主「cejutue」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chijingjing/article/details/104255763

小工具可执行程序看文章附件资源

在这里插入图片描述
在这里插入图片描述

源码下载

Qt开发项目案例-以及部分示例的源码下载链接

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于react native项目中使用react-native-wechat-lib@3.0.4

关于react native项目中使用react-native-wechat-lib3.0.4 插件官网安装依赖包&#xff08;Android和iOS下载插件完成后记得更新依赖&#xff0c;&#xff09;Android中配置1.在项目文件夹下面创建文件夹wxapi&#xff08;如上图&#xff09;2.在文件MainApplication.java中如下…

软件设计师——法律法规(三)

&#x1f4d1;前言 本文主要是【法律法规】——软件设计师——法律法规的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304…

JAVA代码审计之深入XXE漏洞挖掘与防御

文章目录 前言WebGoat1.1 Docker环境搭建1.2 Leve1-XXE回显1.3 代码审计与溯源1.4 Jaxb的反序列化1.5 Level2-格式校验1.6 Level3-XXE盲注 挖掘与防御2.1 XMLReader2.2 SAXBuilder2.3 SAXReader2.4 SAXParserFactory2.5 Digester2.6 DocumentBuilderFactory2.7 XXE挖掘技巧小结…

strlen的三种模拟实现方法

首先&#xff0c;我们要了解strlen函数的参数以及返回值&#xff0c;还有使用方法。 1. 计数器方法 #include <stdio.h>size_t my_strlen(const char* str) {int count 0;while (*str) {count;}return count; } int main() {char arr[] "abcdef";int len …

Angular+Nginx区域HIS医院信息管理系统源码

医院管理信息系统&#xff08;HIS&#xff09;是医院基本、重要的管理系统&#xff0c;是医院大数据的基础。“云”指系统采用云计算的技术和建设模式&#xff0c;具有可扩展、易共享、区域化、易协同、低成本、易维护、体验好的优势。“H”是医疗卫生&#xff0c;由原来医院 (…

Flask学习四:补充

插件 flask-caching 简介 Flask-Caching 是一个 Flask 扩展&#xff0c;旨在为 Flask 应用程序添加缓存功能。缓存是一种提高应用性能的技术&#xff0c;通过将常用数据暂时存储在一个快速访问的位置&#xff08;如内存或磁盘&#xff09;&#xff0c;从而减少对较慢资源&…

ssm基于MVC的舞蹈网站的设计与实现论文

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;舞蹈网站当然也不能排除在外。舞蹈网站是以实际运用为开发背景&#xff0c;运用软件工程开发方法&#xff0c;采用Java技…

自动化测试(终章)webdriver的常用api(2)以及新的开始

目录 多层框架/窗口定位 多层框架的定位 frame是什么&#xff1f; 多层窗口定位 层级定位 使用 XPath 进行层级定位&#xff1a; 使用 CSS 选择器进行层级定位&#xff1a; 下拉框处理 alert、confirm、prompt 的处理 Alert 弹窗&#xff1a; Confirm 弹窗&#xff…

万兆网络之屏蔽线序接法(上)

可以经常听到用RJ45指代网线&#xff0c;用RJ11指代电话线的&#xff0c;RJ&#xff08;Registered Jack&#xff09;即已注册插口&#xff0c;可以简单理解为一种约定就行&#xff08;参见参考链接&#xff09; 前一篇已经讲到&#xff0c;网线线对互相缠绕是为了电流方向相反…

Redis List类型

列表类型是用来存储多个有序的字符串&#xff0c;如图所示&#xff0c;a、b、c、d、e 五个元素从左到右组成了一个有序的列表&#xff0c;列表中的每个字符串称为元素 (element)&#xff0c;一个列表最多可以存储2的32次方 -1个元素。在 Redis 中&#xff0c;可以对列表两端插入…

spring面试:一、面试题分类总览+bean线程安全问题+AOP相关问题(定义、使用步骤、编程式事务管理和声明式事务管理和声明式事务管理失效)

面试题分类总览 bean线程安全问题 单例/多例 单例&#xff08;singleton&#xff09;&#xff1a;在每个spring ioc容器中都只有一个实例。 多例&#xff08;prototype&#xff09;&#xff1a;在每个spring ioc容器中有多个实例。 默认情况下spring中的bean都是单例的。但是…

【星环云课堂大数据实验】kafka消息发布与订阅

文章目录 一、Kafka概述二、实验环境三、实验准备四、实验目的五、实验步骤5.1、创建Kafka Topic5.2、Kafka消息发布5.3、Kafka消息订阅 六、实验感悟 一、Kafka概述 Kafka是由Apache软件基金会开发的一个开源流处理平台&#xff0c;由Scala和Java编写。该项目的目标是为处理实…

算法Day33 不会算数的小明

不会算数的小明 Description 现在有一个数字startValue&#xff0c;小明不会算数&#xff0c;只会以下两种操作&#xff1a; 双倍&#xff08;Double&#xff09;&#xff1a;将数字乘2&#xff1b; 递减&#xff08;Decrement&#xff09;&#xff1a;将数字减1。 给定两个整…

Python3开发笔记(简洁版)

一、开发编辑器 1. pycharm 2. IDLE&#xff08;Python自带软件&#xff09; 方法&#xff1a;Microsoft Store搜索 Python 安装 二、数据类型 Python中有以下几种主要的数据类型&#xff1a; 数字&#xff08;Numbers&#xff09;、 字符串&#xff08;Strings&#xff09…

linux(centos7)mysql8.0主从集群搭建(两台机器)

docker安装:&#xff08;转载&#xff09;centos7安装Docker详细步骤&#xff08;无坑版教程&#xff09;-CSDN博客 环境信息 主数据库服务器&#xff1a;192.168.1.10 从数据库服务器&#xff1a;192.168.1.11 1. mysql8.0镜像下载 docker pull mysql:8.0.23 2.创建docke…

CMS—评论功能设计

一、需求分析 1.1、常见行为 1.敏感词过滤 2.新增评论&#xff08;作品下、评论下&#xff09; 3.删除评论&#xff08;作品作者、上级评论者、本级作者&#xff09; 4.上级评论删除关联下级评论 5.逻辑状态变更&#xff08;上线、下线、废弃...&#xff09; 6.上逻辑状态变更…

图片的批量建码怎么做?一图一码的制作方法

在使用图片展示内容时&#xff0c;经常会有同一类型的图片信息是有区别的&#xff0c;如果需要将每张图片批量生成二维码图片&#xff0c;那么出了一张一张去制作之外&#xff0c;有没有能够一键批量建码的功能可以解决这个问题呢&#xff1f;下面来给大家分享一下图片批量建码…

社交网络分析2(下):社交网络情感分析的方法、挑战与前沿技术

社交网络分析2&#xff08;下&#xff09;&#xff1a;社交网络情感分析的方法、挑战与前沿技术 写在最前面7. 词嵌入&#xff08;word embedding&#xff09;的主要目的是什么&#xff1f;结合某方法简要地说明如何实现词嵌入。主要目的实现方法示例&#xff1a;GloVe案例分析…

透明PP专用UV胶水粘接PP材料高效率的提升生产效率

使用透明PP专用UV胶水粘接PP材料是提高生产效率的方法。以下方法&#xff0c;可以助您在生产中实现高效的PP材料粘接&#xff1a; ​1.选用合适的透明PP专用UV胶水 选择经过专门设计用于透明PP的UV胶水。这种胶水具有透明性&#xff0c;能保证粘接后的清晰度和外观。 2.自动…

Qt中槽函数在那个线程执行的探索和思考

信号和槽是Qt的核心机制之一&#xff0c;通过该机制大大简化了开发者的开发难度。信号和槽属于观察者模式&#xff08;本质上是回调函数的应用&#xff09;。是函数就需要考虑其是在那个线程中执行&#xff0c;本文讨论的就是槽函数在那个线程中执行的问题。 目录 1. connect…