COM - IWbemClassObject对象属性的遍历

文章目录

    • COM - IWbemClassObject对象属性的遍历
    • 概述
    • 笔记
    • 场景
    • 封装好的函数
    • bool CWmiBase::enumObjVaule(IWbemClassObject* obj, std::wstring& val)
    • bool CWmiBase::appendVarToString(BSTR& strName, VARIANT& var, std::wstring& val)
    • bool CWmiBase::get_var_VT_BSTR_VT_ARRAY(VARIANT& var, std::wstring& csResut)
    • bool CWmiBase::getObjVauleByName_bstr_ary(IWbemClassObject* obj, const TCHAR* pszName, std::wstring& val)
    • bool CWmiBase::get_var_VT_I4_VT_ARRAY(VARIANT& var, std::wstring& csResut)
    • bool CWmiBase::getObjVauleByName_var(IWbemClassObject* obj, const TCHAR* pszName, VARIANT& vt_prop)
    • bool CWmiBase::getObjVauleByName_bstr(IWbemClassObject* obj, const TCHAR* pszName, std::wstring& val)
    • 备注
    • END

COM - IWbemClassObject对象属性的遍历

概述

MS官方有一些具体的IWbemClassObject属性的说明, e.g. https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-battery

如果是头一次玩(或者是过了一段时间去玩), 该取哪个属性, 很难讲, 谁知道里面是啥. 看官方描述, 也是知道个大概. 还得拿名字取, 一个一个去实验. 这很麻烦.

因为很麻烦, 就在想, 是否可以遍历出这个IWbemClassObject*, 先看一下, 再有目的的取中意的属性值.
没查到遍历IWbemClassObject的资料.
网上比较常见的代码为给定obj, name, 执行后, 得到value. e.g.

			if (getObjVauleByName_bstr(obj, L"DeviceID", str_tmp)){key.Format(TEXT("DeviceID"));val.Format(TEXT("%s"), str_tmp.c_str());row.m_list.AddTail(C_my_key_val(key, val));}

自己扑腾了2个小时, 搞定. 封装了几个函数.
这样对于新接触的IWbemClassObject, 只需要先用封好的函数遍历一下, 看到全貌(name/value)后. 再明确的取需要的属性, 这样效率提高不止10倍.

笔记

场景

从IEnumWbemClassObject遍历, 得到IWbemClassObject obj
现在obj中有很多属性, 先调用自己封装的enumObjVaule()先将name/value的列表打印到str_tmp, 在调试状态下看一下.

	do {if (!execute_query(query_string)) {break;}while (enumerator) {++index;enumerator->Next(WBEM_INFINITE, 1, &obj, &u_return);if ((0 == u_return) || (NULL == obj)) {break;}enumObjVaule(obj, str_tmp); // 遍历obj, 得到结果列表(name/value)// ...

str_tmp的记录如下:

__PATH = \\LS-PRECISION356\ROOT\CIMV2:Win32_Battery.DeviceID="3689BYDDELL R05P01B"
__NAMESPACE = ROOT\CIMV2
__SERVER = LS-PRECISION356
__DERIVATION = 1463599312
__PROPERTY_COUNT = 33
__RELPATH = Win32_Battery.DeviceID="3689BYDDELL R05P01B"
__DYNASTY = CIM_ManagedSystemElement
__SUPERCLASS = CIM_Battery
__CLASS = Win32_Battery
__GENUS = 2
Availability = 2
BatteryRechargeTime = 
BatteryStatus = 2
Caption = 内部电池
Chemistry = 2
ConfigManagerErrorCode = 
ConfigManagerUserConfig = 
CreationClassName = Win32_Battery
Description = 内部电池
DesignCapacity = 
DesignVoltage = 16419
DeviceID = 3689BYDDELL R05P01B
ErrorCleared = 
ErrorDescription = 
EstimatedChargeRemaining = 100
EstimatedRunTime = 71582788
ExpectedBatteryLife = 
ExpectedLife = 
FullChargeCapacity = 
InstallDate = 
LastErrorCode = 
MaxRechargeTime = 
Name = DELL R05P01B
PNPDeviceID = 
PowerManagementCapabilities = 1;
PowerManagementSupported = false
SmartBatteryVersion = 
Status = OK
StatusInfo = 
SystemCreationClassName = Win32_ComputerSystem
SystemName = LS-PRECISION356
TimeOnBattery = 
TimeToFullCharge = 

这时, 就知道obj中有啥中意的属性要拿了.
然后将enumObjVaule()注释掉, 开始写正式代码.

封装好的函数

bool CWmiBase::enumObjVaule(IWbemClassObject* obj, std::wstring& val)

bool CWmiBase::enumObjVaule(IWbemClassObject* obj, std::wstring& val)
{bool b_rc = false;HRESULT hr;BSTR strName = NULL;VARIANT var;CIMTYPE type;long lFlavor = 0;bool b_tmp = false;CString cs_tmp;int i = 0;do {val.clear();if (NULL == obj){break;}hr = obj->BeginEnumeration(0);if (!SUCCEEDED(hr)){break;}do {hr = obj->Next(0, &strName, &var, &type, &lFlavor);if (FAILED(hr)){break;}if (var.vt != type){// 枚举出来的类型有和var.vt不一样的情况, 还是直接用var.vt// assert(false);}if (NULL == strName){// 如果枚举到的名称为NULL, 就要跳出了.// 否则继续枚举, 不会出错, 陷入死循环.break;}cs_tmp = strName;if (cs_tmp == TEXT("EstimatedRunTime")){int debug = 0; // for debug only}appendVarToString(strName, var, val);++i;} while (true);hr = obj->EndEnumeration();if (!SUCCEEDED(hr)){break;}b_rc = true;} while (false);return b_rc;
}

bool CWmiBase::appendVarToString(BSTR& strName, VARIANT& var, std::wstring& val)

bool CWmiBase::appendVarToString(BSTR& strName, VARIANT& var, std::wstring& val)
{// https://learn.microsoft.com/en-us/windows/win32/api/propidl/ns-propidl-propvariantbool b_rc = false;bool b_tmp = false;CString cs_tmp;std::wstring str_tmp;do {if (NULL == strName){break;}switch (var.vt){//VT_EMPTY = 0,case VT_EMPTY:{cs_tmp.Format(TEXT("%s = %s\n"), strName, TEXT(""));}break;//VT_NULL = 1,case VT_NULL:{cs_tmp.Format(TEXT("%s = %s\n"), strName, TEXT(""));}break;//VT_I2 = 2,case VT_I2:{cs_tmp.Format(TEXT("%s = %d\n"), strName, var.iVal);}break;//VT_I4 = 3,case VT_I4:{cs_tmp.Format(TEXT("%s = %d\n"), strName, var.lVal);}break;//VT_R4 = 4,case VT_R4:{cs_tmp.Format(TEXT("%s = %.2f\n"), strName, var.fltVal);}break;//VT_R8 = 5,case VT_R8:{cs_tmp.Format(TEXT("%s = %.2f\n"), strName, var.dblVal);}break;//VT_CY = 6,case VT_CY:{// 这是英文货币数据, 遇到再调试assert(false);// cs_tmp.Format(TEXT("%s = %d\n"), strName, var.pcyVal);}break;//VT_DATE = 7,case VT_DATE:{// 这是日期数据, 遇到再调试assert(false);// cs_tmp.Format(TEXT("%s = %d\n"), strName, var.date);}break;//VT_BSTR = 8,case VT_BSTR:{cs_tmp.Format(TEXT("%s = %s\n"), strName, var.bstrVal);}break;//VT_DISPATCH = 9,case VT_DISPATCH:{assert(false); // 遇到再调试// cs_tmp.Format(TEXT("%s = %d\n"), strName, var.pdispVal);}break;//VT_ERROR = 10,case VT_ERROR:{assert(false); // 遇到再调试// cs_tmp.Format(TEXT("%s = %d\n"), strName, var.scode);}break;//VT_BOOL = 11,case VT_BOOL:{cs_tmp.Format(TEXT("%s = %s\n"), strName, (var.boolVal ? TEXT("true") : TEXT("false")));}break;//VT_VARIANT = 12, // 官方文档有说明, 但是实际结构没有对应的变量 var.capropvar//VT_UNKNOWN = 13,case VT_UNKNOWN:{assert(false); // 遇到再调试// cs_tmp.Format(TEXT("%s = %d\n"), strName, var.punkVal);}break;//VT_DECIMAL = 14,case VT_DECIMAL:{assert(false); // 遇到再调试// cs_tmp.Format(TEXT("%s = %d\n"), strName, var.decVal);}break;//VT_I1 = 16,case VT_I1:{cs_tmp.Format(TEXT("%s = %d\n"), strName, var.cVal);}break;//VT_UI1 = 17,case VT_UI1:{cs_tmp.Format(TEXT("%s = %d\n"), strName, var.bVal);}break;//VT_UI2 = 18,case VT_UI2:{cs_tmp.Format(TEXT("%s = %d\n"), strName, var.uiVal);}break;//VT_UI4 = 19,case VT_UI4:{cs_tmp.Format(TEXT("%s = %d\n"), strName, var.ulVal);}break;//VT_I8 = 20, // 官方文档有说明, 但是实际结构没有对应变量 var.hVal//VT_UI8 = 21, // 官方文档有说明, 但是实际结构没有对应变量 var.uhVal//VT_INT = 22,case VT_INT:{cs_tmp.Format(TEXT("%s = %d\n"), strName, var.intVal);}break;//VT_UINT = 23,case VT_UINT:{cs_tmp.Format(TEXT("%s = %d\n"), strName, var.uintVal);}break;//VT_VOID = 24, // 官方没有这个定义的解释//VT_HRESULT = 25, // 官方没有这个定义的解释//VT_PTR = 26, // 官方没有这个定义的解释//VT_SAFEARRAY = 27, // 官方没有这个定义的解释//VT_CARRAY = 28, // 官方没有这个定义的解释//VT_USERDEFINED = 29, // 官方没有这个定义的解释//VT_LPSTR = 30, // 官方文档有说明, 但是实际结构没有对应变量 var.pszVal//VT_LPWSTR = 31, // 官方文档有说明, 但是实际结构没有对应变量 var.pwszVal//VT_RECORD = 36, // 官方没有这个定义的解释//VT_INT_PTR = 37, // 官方没有这个定义的解释//VT_UINT_PTR = 38,// 官方没有这个定义的解释//VT_FILETIME = 64, // 官方文档有说明, 但是实际结构没有对应变量 var.filetime//VT_BLOB = 65, // 官方文档有说明, 但是实际结构没有对应变量 var.blob//VT_STREAM = 66, // 官方文档有说明, 但是实际结构没有对应变量 var.pStream//VT_STORAGE = 67, // 官方文档有说明, 但是实际结构没有对应变量 var.pStorage//VT_STREAMED_OBJECT = 68, // 官方文档有说明, 但是实际结构没有对应变量 var.pStream//VT_STORED_OBJECT = 69, // 官方文档有说明, 但是实际结构没有对应变量 var.pStorage//VT_BLOB_OBJECT = 70, // 官方文档有说明, 但是实际结构没有对应变量 var.blob//VT_CF = 71, // 官方文档有说明, 但是实际结构没有对应变量 var.pclipdata//VT_CLSID = 72, // 官方文档有说明, 但是实际结构没有对应变量 var.puuid//VT_VERSIONED_STREAM = 73, // 官方文档有说明, 但是实际结构没有对应变量 var.pVersionedStream//VT_BSTR_BLOB = 0xfff, // 官方文档有说明, 但是实际结构没有对应变量 var.bstrblobVal//VT_VECTOR = 0x1000, // 这个是和其他.vt组合用的, 不能单独处理//VT_ARRAY = 0x2000,//VT_BYREF = 0x4000, // 这个是和其他.vt组合用的, 不能单独处理//VT_RESERVED = 0x8000, // 官方没有文档说明//VT_ILLEGAL = 0xffff, // 官方没有文档说明//VT_ILLEGALMASKED = 0xfff, // 官方没有文档说明//VT_TYPEMASK = 0xfff // 这个是和其他.vt组合用的, 不能单独处理// var.vt = 0x2008case (VT_BSTR | VT_ARRAY):{b_tmp = get_var_VT_BSTR_VT_ARRAY(var, str_tmp);assert(b_tmp);cs_tmp.Format(TEXT("%s = %s\n"), strName, str_tmp.data());}break;// var.vt = 0x2003case (VT_I4 | VT_ARRAY):{b_tmp = get_var_VT_I4_VT_ARRAY(var, str_tmp);assert(b_tmp);cs_tmp.Format(TEXT("%s = %s\n"), strName, str_tmp.data());}break;default:_ASSERT(false); // 未处理的.vt, 加了断言, 等遇到后再处理.break;}b_rc = true;} while (false);if (!cs_tmp.IsEmpty()){val += cs_tmp.GetString();}assert(b_rc);return b_rc;
}

bool CWmiBase::get_var_VT_BSTR_VT_ARRAY(VARIANT& var, std::wstring& csResut)

bool CWmiBase::get_var_VT_BSTR_VT_ARRAY(VARIANT& var, std::wstring& csResut)
{// COM - get VARIANT value - .vt = (VT_BSTR | VT_ARRAY)//! \ref VC2008Samples\MFC\general\VariantUsebool b_rc = false;LONG ary_index_low = 0;LONG ary_index_up = 0;LONG i = 0;HRESULT hr;BSTR* _bstr = NULL;bool b_tmp = false;do {csResut.clear();if ((VT_BSTR | VT_ARRAY) != var.vt){_ASSERT(FALSE);break;}if (NULL == var.parray){break;}hr = SafeArrayAccessData(var.parray, (void**)&_bstr); //access the array stored in the varriant.do {if (NULL == _bstr){break;}hr = SafeArrayGetLBound(var.parray, 1, &ary_index_low);if (!SUCCEEDED(hr)){break;}hr = SafeArrayGetUBound(var.parray, 1, &ary_index_up);if (!SUCCEEDED(hr)){break;}for (i = ary_index_low; i <= ary_index_up; i++){csResut += _bstr[i];csResut += TEXT(";");}} while (false);SafeArrayUnaccessData(var.parray);b_rc = true;} while (false);return b_rc;
}

bool CWmiBase::getObjVauleByName_bstr_ary(IWbemClassObject* obj, const TCHAR* pszName, std::wstring& val)

bool CWmiBase::getObjVauleByName_bstr_ary(IWbemClassObject* obj, const TCHAR* pszName, std::wstring& val)
{bool b_rc = false;VARIANT vt_prop;CString csResut;do {val.clear();if (!getObjVauleByName_var(obj, pszName, vt_prop)){break;}if ((VT_BSTR | VT_ARRAY) != vt_prop.vt){_ASSERT(FALSE);break;}get_var_VT_BSTR_VT_ARRAY(vt_prop, val);// val = vt_prop.bstrVal;b_rc = true;} while (false);VariantClear(&vt_prop);return b_rc;
}

bool CWmiBase::get_var_VT_I4_VT_ARRAY(VARIANT& var, std::wstring& csResut)

bool CWmiBase::get_var_VT_I4_VT_ARRAY(VARIANT& var, std::wstring& csResut)
{// COM - get VARIANT value - .vt = (VT_BSTR | VT_ARRAY)//! \ref VC2008Samples\MFC\general\VariantUsebool b_rc = false;LONG ary_index_low = 0;LONG ary_index_up = 0;LONG i = 0;HRESULT hr;LONG* lVal = NULL;bool b_tmp = false;CString cs_tmp;do {csResut.clear();if ((VT_I4 | VT_ARRAY) != var.vt){_ASSERT(FALSE);break;}if (NULL == var.parray){break;}hr = SafeArrayAccessData(var.parray, (void**)&lVal); //access the array stored in the varriant.do {if (NULL == lVal){break;}hr = SafeArrayGetLBound(var.parray, 1, &ary_index_low);if (!SUCCEEDED(hr)){break;}hr = SafeArrayGetUBound(var.parray, 1, &ary_index_up);if (!SUCCEEDED(hr)){break;}for (i = ary_index_low; i <= ary_index_up; i++){cs_tmp.Format(TEXT("%d"), lVal[i]);csResut += cs_tmp.GetString();csResut += TEXT(";");}} while (false);SafeArrayUnaccessData(var.parray);b_rc = true;} while (false);return b_rc;
}

bool CWmiBase::getObjVauleByName_var(IWbemClassObject* obj, const TCHAR* pszName, VARIANT& vt_prop)

bool CWmiBase::getObjVauleByName_var(IWbemClassObject* obj, const TCHAR* pszName, VARIANT& vt_prop)
{bool b_rc = false;HRESULT hr;do {if ((NULL == obj) || (NULL == pszName)){break;}hr = obj->Get(pszName, 0, &vt_prop, NULL, NULL);if (!SUCCEEDED(hr)){break;}// https://learn.microsoft.com/en-us/windows/win32/api/wtypes/ne-wtypes-varenumif ((VT_EMPTY == vt_prop.vt) || (VT_NULL == vt_prop.vt)){break;}b_rc = true;} while (false);return b_rc;
}

bool CWmiBase::getObjVauleByName_bstr(IWbemClassObject* obj, const TCHAR* pszName, std::wstring& val)

bool CWmiBase::getObjVauleByName_bstr(IWbemClassObject* obj, const TCHAR* pszName, std::wstring& val)
{bool b_rc = false;VARIANT vt_prop;do {val.clear();if (!getObjVauleByName_var(obj, pszName, vt_prop)){break;}if (VT_BSTR != vt_prop.vt){_ASSERT(FALSE);break;}val = vt_prop.bstrVal;b_rc = true;} while (false);VariantClear(&vt_prop);return b_rc;
}

备注

没有处理全部var.vt, 加了断言, 等遇到后再处理.

END

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

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

相关文章

【笔试强训错题选择题】Day5.习题(错题)解析

文章目录 前言 错题题目 错题解析 总结 前言 错题题目 1. ​ ​ 2. 3. ​ 4. ​ 5. ​ 错题解析 1. 移位运算符的使用 2. 3. 4. 5. 总结

如何用TCC实现分布式事务?

TCC事务介绍 TCC&#xff08;Try-Confirm-Cancel&#xff09;是除可靠消息队列以外的另一种常见的分布式事务机制&#xff0c;它是由数据库专家帕特 赫兰德&#xff08;Pat Helland&#xff09;在2007年撰写的论文《Life beyond Distributed Transactions: An Apostate’s Op…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的体育赛事目标检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;开发和研究体育赛事目标检测系统对于增强体育分析和观赏体验至关重要。本篇博客详细讲述了如何运用深度学习技术构建一个体育赛事目标检测系统&#xff0c;并提供了完整的实现代码。系统基于先进的YOLOv8算法&#xff0c;对比了YOLOv7、YOLOv6、YOLOv5的性能&a…

【webrtc】p2p_transport_channel 中忽略Hyper-V

【win11】更改网络适配器设置 删掉了hype-v,这时候wsl2 打不开了,但是重启后,还是存在hyper-v那么,让webrtc自己不适用hyper-v的网络Hyper-V 的全程:Hyper-V Virtual Ethernet Adapter https://github.com/SophistSolutions/Stroika/blob/2cd5e8bf4ee01cb5c423367b4df628f…

MFC 模态对话框退出机制的探究

一位读者问了这样一个问题: ” 如果我创建了一个可见的模态对话框,却对用户来说不可用。举个例子,假设我在程序中的其他位置收到一个事件,并且我从事件中调用模态 CDialog 上的 DestroyWindow。我注意到 OnDestroy 是在 CDialog 上调用的,但在将 WM_QUIT 消息发送到模态对…

在MyBatis中自定义JsonTypeHandler

在MyBatis中使用自定义的JsonTypeHandler 在处理数据库中的JSON字段时&#xff0c;我们经常需要将JSON字符串映射到Java对象&#xff0c;或者将Java对象序列化为JSON字符串以存储在数据库中。MyBatis作为一个流行的Java持久层框架&#xff0c;允许我们通过自定义类型处理器&am…

爬虫入门到精通_实战篇7(Requests+正则表达式爬取猫眼电影)_ 抓取单页内容,正则表达式分析,保存至文件,开启循环及多线程

1 目标 猫眼榜单TOP100&#xff1a;https://www.maoyan.com/board 2 流程框架 抓取单页内容&#xff1a;利用requests请求目标站点&#xff0c;得到单个网页HTML代码&#xff0c;返回结果。正则表达式分析&#xff1a;根据HTML代码分析得到电影名称,主演,上映时间,评分,图片…

跨域问题与解决方法

跨域问题与解决方法 同源策略 浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议域名端口"三者相同&#xff0c;即便两个不同的域名指向同一个ip地址&#xff0c;也非同源。 同源策略限制以下几种行为&#xff1a; Cookie、LocalStorage 和 IndexDB 无法读取 DO…

C语言中的分支和循环语句:从入门到精通

分支和循环语句 1. 前言2. 预备知识2.1 getchar函数2.2 putchar函数2.3 计算数组的元素个数2.4 清屏2.5 程序的暂停2.6 字符串的比较 3. 结构化3.1 顺序结构3.2 分支结构3.3 循环结构 4. 真假性5. 分支语句&#xff08;选择结构&#xff09;5.1 if语句5.1.1 语法形式5.1.2 else…

Java网络通信UDP

目录 网络通信基础 UDP通信 服务器 1.想要使用UDP通信 要先打开DatagramSocket文件 端口号可以手动指定或系统随机分配 2.阻塞等待接收客户端数据&#xff1b;创建DatagramPacket接收客户端传来的数据 3.处理客户端传来的数据&#xff0c;并进行业务处理&#xff08;这里…

MySQL 教程 2.4

MySQL UNION 操作符 本教程为大家介绍 MySQL UNION 操作符的语法和实例。 描述 MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合&#xff0c;并去除重复的行。 UNION 操作符必须由两个或多个 SELECT 语句组成&#xff0c;每个 SELECT 语句的列数…

Python降维数据库之umap使用详解

概要 在数据科学和机器学习领域,数据通常是高维度的,而高维度数据不仅难以可视化,还会增加建模的复杂性。降维是一种处理高维数据的关键技术,而Python UMAP(Uniform Manifold Approximation and Projection)是一种强大的降维工具,它在保留数据结构的同时,将高维数据映…

uni-app引用外部js文件

全局引用 在App.vue文件中添加如下代码 这样在全局所有页面中都可以直接使用该外部js中的函数 onLaunch: function() {var script document.createElement(script);script.src "https://www.test.com/api/testapi.js";document.body.appendChild(script); }, 单…

【IDEA+通义灵码插件】实现属于你的大模型编程助手

目录 1.前言 2.下载安装 3.解释代码 4.生成单元测试 5.生成注释 6.智能补全 1.前言 大模型到底该以一种什么方式落地&#xff0c;从而嵌入我们的工作当中&#xff0c;助力我们工作效率的提升&#xff0c;其实最好的方式也许就是虚拟助手的方式&#xff0c;就像钢铁侠的&…

【OpenCV基础(三)】Ubuntu系统下EasyPR环境配置

环境配置 1、资源下载2、环境配置2.1、1、将EasyPR压缩包拷贝到Ubuntu 三种方法任选一种2.2、解压得到EasyPR文件夹(文件夹一层进入后EasyPR资源内容)2.3、终端命令修改权限**chmod -R 777 ./ EasyPR**2.4、查找EasyPR/include/easypr/config.h&#xff0c;使用gedit方式打开2.…

uni-app app实现web-view H5图片长按下载

问题和使用场景描述&#xff1a; uniapp app web-view中图片无法长按保存&#xff0c;IOS下是正常的&#xff0c;但是Android下长按无反应 解决方案&#xff1a; 下载mui.min.js&#xff0c;放到项目中的static下(下载见最上面的压缩包) 在static目录下新建script.js mui.…

vue2本地开发环境正常,生产环境下this.$router.push({ name: ‘login‘ })不跳转

如果在Vue.js 2中在本地开发环境下正常运行,但在生产环境下使用​​this.$router.push({ name: login })​​不起作用,可能有几个原因需要检查和解决: 路由配置问题: 确保你的路由配置正确,特别是确保在生产环境中,路由的配置和本地开发环境一致。检查是否正确设置了name…

基于springboot+vue的智能学习平台系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

SAP PP学习笔记 - 豆知识07 - 如何查看BOM一览

SAP标准提供了CS03&#xff0c;只能查询单个的BOM&#xff0c;如果想查看一览&#xff0c;只能自己写SQVI 查询。 有其他高招的童鞋&#xff0c;请赐教啊。 1&#xff0c;SQVI 工具 SAP MM学习笔记18- SQVI 工具_sap sqvi-CSDN博客 输入查询名&#xff0c;然后点击 登录 2&a…

#QT(DEMO2-登录界面)

1.IDE&#xff1a;QTCreator 2.实验&#xff1a;DEMO登录 3.记录 Line Edit输入不换行 密码框输入如下设置: 运行效果 4.代码