Qt案例 调用WINDOWS API中的SETUPAPI.H库获取设备管理器中设备的详细信息中的属性值(二)

使用Qt调用windows api中的setupapi.h库中的SetupDiGetDeviceRegistryPropertySetupDiGetDeviceProperty函数获取设备管理器中的设备详细信息中的属性值,包括设备实例路径,硬件id,驱动inf名称,驱动版本,显示名称,类名,供应商,设备描述等属性值。

目录导读

  • 实现效果
  • 相关函数的说明
    • SetupDiGetDeviceRegistryProperty 函数
      • 封装SetupDiGetDeviceRegistryProperty 函数调用
      • 调用示例 :
    • SetupDiGetDeviceProperty 函数
      • 封装SetupDiGetDeviceProperty 函数调用
      • 调用示例:
  • 常见DEVPROPTYPE数据类型处理
    • DEVPROPTYPE数据类型说明:
    • PBYTE类型数据转DEVPROPTYPE数据类型相关结构
      • DEVPROP_TYPE_GUID 数据类型处理
      • DEVPROP_TYPE_STRING数据类型处理
      • DEVPROP_TYPE_STRING_LIST数据类型处理
      • DEVPROP_TYPE_FILETIME数据类型处理

实现效果

根据左侧选择的设备管理器,设备实例路径
获取设备大部分DEFINE_DEVPROPKEY属性对应的业务值
并显示到右侧文本框中。
在这里插入图片描述

相关函数的说明

涉及到以下函数的使用:

  • SetupDiGetDeviceRegistryProperty 函数

SetupDiGetDeviceRegistryProperty 函数检索指定的即插即用设备属性。
语法:

//! 如果调用成功,SetupDiGetDeviceRegistryProperty 将返回 TRUE。 否则,它将返回 FALSE ,并且可以通过调用 GetLastError 来检索记录的错误。 如果设备不存在请求的属性或属性数据无效,SetupDiGetDeviceRegistryProperty 将返回ERROR_INVALID_DATA错误代码。
WINSETUPAPI BOOL SetupDiGetDeviceRegistryPropertyW([in]            HDEVINFO         DeviceInfoSet, //设备信息集的句柄,其中包含表示要为其检索即插即用属性的设备的设备信息元素。[in]            PSP_DEVINFO_DATA DeviceInfoData, //指向 SP_DEVINFO_DATA 结构的指针,该结构指定 DeviceInfoSet 中的设备信息元素。[in]            DWORD            Property, //指定要检索的属性[out, optional] PDWORD           PropertyRegDataType, //指向接收所检索属性的数据类型的变量的指针。 这是标准注册表数据类型之一。 此参数是可选的,可以为 NULL。[out, optional] PBYTE            PropertyBuffer, //指向接收正在检索的属性的缓冲区的指针。 如果此参数设置为 NULL,并且 PropertyBufferSize 也设置为零,则该函数将返回 RequiredSize 中缓冲区的所需大小。[in]            DWORD            PropertyBufferSize, //PropertyBuffer 缓冲区的大小(以字节为单位)。[out, optional] PDWORD           RequiredSize //指向类型为 DWORD 的变量的指针,该变量接收保存所请求属性的数据所需的 PropertyBuffer 缓冲区的所需大小(以字节为单位)。 此参数是可选的,可以为 NULL。
);
  • 封装SetupDiGetDeviceRegistryProperty 函数调用

使方法通用,主要也是为了避免分配内存不足导致的异常的问题。
方法中的DeviceInfoSetDeviceInfoData都是SetupDiGetClassDevsSetupDiEnumDeviceInfo获取的值,详见专栏上一篇。

bool GetSetupDiGetDeviceRegistryProperty(HDEVINFO DeviceInfoSet,PSP_DEVINFO_DATA DeviceInfoData,DWORD Property,PBYTE& PropertyBuffer,DWORD& requiredSize) const
{bool result =SetupDiGetDeviceRegistryProperty(DeviceInfoSet,DeviceInfoData,Property,0,PropertyBuffer,requiredSize,&requiredSize);if(!result && GetLastError()==ERROR_INSUFFICIENT_BUFFER){PropertyBuffer=(PBYTE)malloc(requiredSize);result = SetupDiGetDeviceRegistryProperty(DeviceInfoSet,DeviceInfoData,Property,0,PropertyBuffer,requiredSize,NULL);}if(!result)qDebug()<<"Function SetupDiGetDeviceRegistryProperty Execution failure!";return result;
}
  • 调用示例 :

获取SPDRP_FRIENDLYNAME
检索包含设备的友好名称的REG_SZ字符串

 PBYTE FriendlyName=(PBYTE)new WCHAR[MAX_PATH];if(GetSetupDiGetDeviceRegistryProperty(DeviceInfoSet, DeviceInfoData,SPDRP_FRIENDLYNAME,FriendlyName, requiredSize))qDebug()<<"SPDRP_FRIENDLYNAME: "<<QString::fromWCharArray((WCHAR*)FriendlyName);

获取SPDRP_UPPERFILTERS
检索包含设备上层筛选器驱动程序名称的REG_MULTI_SZ字符串。

PBYTE buffer=new BYTE [MAX_PATH];
if(GetSetupDiGetDeviceRegistryProperty(deviceInfoSet,&deviceInfoData,SPDRP_UPPERFILTERS,buffer))qDebug()<<"SPDRP_CLASS : "<<QString::fromWCharArray((TCHAR*)buffer);
  • SetupDiGetDeviceProperty 函数

SetupDiGetDeviceProperty 函数检索设备实例属性。

  • 语法:
//! 如果成功,则返回 TRUE 。 否则,它将返回 FALSE,并且可以通过调用 GetLastError 来检索记录的错误。
WINSETUPAPI BOOL SetupDiGetDevicePropertyW([in]            HDEVINFO         DeviceInfoSet, //包含要检索设备实例属性的设备实例的设备信息集的句柄。[in]            PSP_DEVINFO_DATA DeviceInfoData, //指向 SP_DEVINFO_DATA 结构的指针,该结构表示要为其检索设备实例属性的设备实例。[in]            const DEVPROPKEY *PropertyKey, //指向 DEVPROPKEY 结构的指针,该结构表示所请求的设备实例属性的设备属性键。[out]           DEVPROPTYPE      *PropertyType, /*指向 DEVPROPTYPE 类型变量的指针,该变量接收请求的设备实例属性的 property-data-type 标识符,其中 property-data-type 标识符是基数据类型标识符与 base-data 类型修饰符之间的按位 OR。*/[out, optional] PBYTE            PropertyBuffer, /*指向接收请求的设备实例属性的缓冲区的指针。 仅当缓冲区大到足以保存所有属性值数据时,SetupDiGetDeviceProperty 才检索请求的属性。 指针可以为 NULL。 如果指针设置为 NULL 并提供 RequiredSize , 则 SetupDiGetDeviceProperty 将在 *RequiredSize 中返回属性的大小(以字节为单位)。*/[in]            DWORD            PropertyBufferSize, /*PropertyBuffer 缓冲区的大小(以字节为单位)。 如果 PropertyBuffer 设置为 NULL, 则 PropertyBufferSize 必须设置为零。*/[out, optional] PDWORD           RequiredSize, /*指向 DWORD 类型变量的指针,该变量接收设备实例属性(如果检索到属性)的大小(以字节为单位),如果缓冲区不够大,则接收所需的缓冲区大小。 此指针可以设置为 NULL。*/[in]            DWORD            Flags //该参数必须设置为零。
);
  • 封装SetupDiGetDeviceProperty 函数调用

让任何 DEVPROPTYPE 类型的参数都能够直接调用,也是为了避免分配内存不足导致的异常的问题。
方法中的DeviceInfoSetDeviceInfoData参数都是通过SetupDiGetClassDevsSetupDiEnumDeviceInfo获取的值,详见专栏上一篇。

bool GetSetupDiGetDeviceProperty(HDEVINFO deviceInfoSet,PSP_DEVINFO_DATA deviceInfoData,DEVPROPTYPE propType,const DEVPROPKEY * Key,PBYTE& buffer,DWORD& requiredSize) const
{if(requiredSize==0)requiredSize=sizeof(buffer);bool result = SetupDiGetDeviceProperty(deviceInfoSet, deviceInfoData, Key,&propType, buffer, requiredSize, &requiredSize, 0);if(!result && GetLastError()==ERROR_INSUFFICIENT_BUFFER){buffer=(PBYTE)malloc(requiredSize);result = SetupDiGetDeviceProperty(deviceInfoSet, deviceInfoData, Key,&propType, buffer, requiredSize, NULL, 0);}//! 常见异常if(!result){switch (GetLastError()) {case ERROR_INVALID_FLAGS :qDebug()<<"Flags 的值不为零。";break;case ERROR_INVALID_HANDLE :qDebug()<<"DevInfoSet 指定的设备信息集无效。";break;case ERROR_INVALID_PARAMETER :qDebug()<<"提供的参数无效。 一种可能性是设备信息元素无效。";break;case ERROR_INVALID_REG_PROPERTY :qDebug()<<"PropertyKey 提供的属性键无效或属性不可写。";break;case ERROR_INVALID_DATA :qDebug()<<"PropertyType 提供的属性数据类型标识符或 PropertyBuffer 提供的属性值无效。";break;case ERROR_INVALID_USER_BUFFER :qDebug()<<"用户缓冲区无效。 一种可能性是 PropertyBuffer 为 NULL, PropertyBufferSize 不为零。";break;case ERROR_NO_SUCH_DEVINST :qDebug()<<"DevInfoData 指定的设备实例不存在。";break;case ERROR_INSUFFICIENT_BUFFER :qDebug()<<"传递给系统调用的内部数据缓冲区太小。";break;case ERROR_NOT_ENOUGH_MEMORY :qDebug()<<"系统内存不足,无法完成操作。";break;case ERROR_NOT_FOUND :qDebug()<<"找不到未指定的内部元素。 一种可能性是要删除的属性不存在。";break;case ERROR_ACCESS_DENIED :qDebug()<<"调用方没有管理员权限。";break;default:qDebug()<<"get SetupDiGetDeviceProperty is Error!"<<QString::fromWCharArray(Lib_ExtrationDrives::guid_to_wstring(Key->fmtid)) ;}}return result;
}
  • 调用示例:

获取 DEVPKEY_NAME
设备属性表示设备实例的名称。

  DWORD requiredSize=0;PBYTE buffer=new BYTE [MAX_PATH];if(GetSetupDiGetDeviceProperty(DeviceInfoSet,DeviceInfoData,DEVPROP_TYPE_STRING,&DEVPKEY_NAME,buffer,requiredSize)){QString Values=QString::fromWCharArray((TCHAR*)buffer);}

获取 DEVPKEY_Device_DeviceDesc
设备属性表示设备实例的说明。

  DWORD requiredSize=0;PBYTE buffer=new BYTE [MAX_PATH];if(GetSetupDiGetDeviceProperty(DeviceInfoSet,DeviceInfoData,DEVPROP_TYPE_STRING,&DEVPKEY_Device_DeviceDesc,buffer,requiredSize)){QString Values=QString::fromWCharArray((TCHAR*)buffer);}

获取 DEVPKEY_Device_HardwareIds
设备属性表示设备实例的硬件标识符列表。

  DWORD requiredSize=0;PBYTE buffer=new BYTE [MAX_PATH];if(GetSetupDiGetDeviceProperty(DeviceInfoSet,DeviceInfoData,DEVPROP_TYPE_STRING_LIST,&DEVPKEY_Device_HardwareIds,buffer,requiredSize)){QString Values=QString::fromWCharArray((TCHAR*)buffer);}

常见DEVPROPTYPE数据类型处理

DEVPROPTYPE数据类型说明:

属性数据类型标识符

DEVPROPTYPE数据类型Value描述
DEVPROP_TYPE_EMPTY0x00000000无任何属性数据
DEVPROP_TYPE_NULL0x00000001Null 属性数据
DEVPROP_TYPE_SBYTE0x000000028 位有符号 int (SBYTE)
DEVPROP_TYPE_BYTE0x000000038 位无符号 int (BYTE)
DEVPROP_TYPE_INT160x0000000416 位有符号 int (SHORT)
DEVPROP_TYPE_UINT160x0000000516 位无符号 int (USHORT)
DEVPROP_TYPE_INT320x0000000632 位有符号 int (LONG)
DEVPROP_TYPE_UINT320x0000000732 位无符号 int (ULONG)
DEVPROP_TYPE_INT640x0000000864 位有符号 int (LONG64)
DEVPROP_TYPE_UINT640x0000000964 位无符号 int (ULONG64)
DEVPROP_TYPE_FLOAT0x0000000A32 位浮点 (FLOAT)
DEVPROP_TYPE_DOUBLE0x0000000B64 位浮点 (DOUBLE)
DEVPROP_TYPE_DECIMAL0x0000000C128 位数据 (十进制)
DEVPROP_TYPE_GUID0x0000000D128 位唯一标识符 (GUID)
DEVPROP_TYPE_CURRENCY0x0000000E64 位有符号 int 货币值 (CURRENCY)
DEVPROP_TYPE_DATE0x0000000Fdate (DATE)
DEVPROP_TYPE_FILETIME0x00000010file time (FILETIME)
DEVPROP_TYPE_BOOLEAN0x000000118 位布尔 (DEVPROP_BOOLEAN)
DEVPROP_TYPE_STRING0x00000012以 Null 结尾的字符串
DEVPROP_TYPE_STRING_LIST |DEVPROP_TYPE_STRING|DEVPROP_TYPEMOD_LIST多 sz 字符串列表
DEVPROP_TYPE_SECURITY_DESCRIPTOR0x00000013自相对二进制SECURITY_DESCRIPTOR
DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING0x00000014SDDL 格式 (安全描述符字符串)
DEVPROP_TYPE_DEVPROPKEY0x00000015设备属性键 (DEVPROPKEY)
DEVPROP_TYPE_DEVPROPTYPE0x00000016设备属性类型 (DEVPROPTYPE)
DEVPROP_TYPE_BINARY |DEVPROP_TYPE_BYTE |DEVPROP_TYPEMOD_ARRAY自定义二进制数据
DEVPROP_TYPE_ERROR0x0000001732 位 Win32 系统错误代码
DEVPROP_TYPE_NTSTATUS0x0000001832 位 NTSTATUS 代码
DEVPROP_TYPE_STRING_INDIRECT0x00000019字符串资源 (@[path],-)

下面是可能的DEVPROP_TYPEMOD_值:

标识含义
DEVPROP_TYPEMOD_ARRAY0x00001000固定大小的数据元素数组
DEVPROP_TYPEMOD_LIST0x00002000可变大小的数据元素列表

PBYTE类型数据转DEVPROPTYPE数据类型相关结构

  • DEVPROP_TYPE_GUID 数据类型处理

  • 将 PropertyType 参数设置为 DEVPROP_TYPE_GUID,将 PropertyBuffer 参数设置为指向包含 GUID 值的缓冲区的指针,并将 PropertyBufferSize 参数设置为 sizeof(GUID)。
  • 可以直接将PBYTE强制转换成GUID*类型
    如获取:
    DEVPKEY_Device_ClassGuid(实例所属的设备安装类的GUID)
    DEVPKEY_Device_BusTypeGuid(设备实例的总线类型的 GUID)
PBYTE Guidbuffer=new BYTE [MAX_PATH];
if(GetSetupDiGetDeviceProperty(DeviceInfoSet,DeviceInfoData,DEVPROP_TYPE_GUID ,&DEVPKEY_Device_ClassGuid,Guidbuffer,requiredSize)){GUID* classguid=(GUID*)Guidbuffer;QString  Values=QString::fromWCharArray(guid_to_wstring(*classguid));}
  • DEVPROP_TYPE_STRING数据类型处理

  • 将 PropertyType 参数设置为 DEVPROP_TYPE_STRING,将 PropertyBuffer 参数设置为指向包含 NULL 终止 Unicode 字符串的缓冲区的指针,并将 PropertyBufferSize 参数设置为字符串的大小(以字节为单位),包括 NULL 终止符
  • 可以直接将PBYTE强制转换成TCHAR*类型
    如获取:
    DEVPKEY_NAME (设备实例的名称)
    DEVPKEY_Device_DeviceDesc (设备实例的说明)
    DEVPKEY_Device_Service (设备实例安装的服务的名称)
    DEVPKEY_Device_DriverVersion (安装在设备实例上的驱动程序的版本)
    DEVPKEY_Device_DriverInfPath (安装设备实例的 INF 文件的名称)
 //!  DEVPROP_TYPE_STRING 数据类型PBYTE buffer=new BYTE [MAX_PATH];if(GetSetupDiGetDeviceProperty(DeviceInfoSet,DeviceInfoData,DEVPROP_TYPE_STRING,&DEVPKEY_NAME,buffer,requiredSize)){QString  Values=QString::fromWCharArray((TCHAR*)buffer);}
  • DEVPROP_TYPE_STRING_LIST数据类型处理

  • 将 PropertyType 参数设置为 DEVPROP_TYPE_STRING_LIST,将 PropertyBuffer 参数设置为指向包含 unicode 字符串 REG_MULTI_SZ 列表的缓冲区的指针,并将 PropertyBufferSize 参数设置为列表的大小(以字节为单位),包括最终列表 NULL 终止符
  • 可以读多段字符串,\0表示一段结束 \0\0表示全部结束
    如获取:
    DEVPKEY_Device_HardwareIds(设备实例的硬件标识符列表)
    DEVPKEY_DEVICE_CompatibleIds(设备实例的兼容标识符列表)
 PBYTE buffer=new BYTE [MAX_PATH];
if(GetSetupDiGetDeviceProperty(DeviceInfoSet,DeviceInfoData,DEVPROP_TYPE_STRING_LIST,&DEVPKEY_Device_HardwareIds,buffer,requiredSize))
{WCHAR* bufferStr=(WCHAR*)buffer;QStringList valueList;int col=0;WCHAR* item=new WCHAR [MAX_PATH];for(int i=0;i<requiredSize;i++){if(bufferStr[i]!='\0'){item[col]=bufferStr[i];col++;}else{item[col]='\0';valueList.append(QString::fromWCharArray(item));free(item);if(i+1<requiredSize &&bufferStr[i+1]=='\0' )break;item=new WCHAR [MAX_PATH];col=0;}}QString Values=valueList.join("<br/>");
}
  • DEVPROP_TYPE_FILETIME数据类型处理

将 PropertyType 参数设置为 DEVPROP_TYPE_DATE,将 PropertyBuffer 参数设置为指向包含 FILETIME 结构的缓冲区的指针,并将 PropertyBufferSize 参数设置为 sizeof(FILETIME)。
如获取:
DEVPKEY_Device_InstallDate (指定上次在系统中安装设备实例时的时间戳)
DEVPKEY_Device_FirstInstallDate(指定首次在系统中安装设备实例时的时间戳)
DEVPKEY_Device_DriverDate(表示当前为设备实例安装的驱动程序的日期)

auto FileTimeToString=[&](const FILETIME& ft)->QString{SYSTEMTIME st;FileTimeToSystemTime(&ft, &st);// 如果需要转换为特定时区的时间,可以使用SystemTimeToTzSpecificLocalTime函数// 但这里我们假设只需要本地时间return  QString("%1-%2-%3 %4:%5:%6").arg(st.wYear,4,10,QLatin1Char('0')).arg(st.wMonth,2,10,QLatin1Char('0')).arg(st.wDay,2,10,QLatin1Char('0')).arg(st.wHour,2,10,QLatin1Char('0')).arg(st.wMinute,2,10,QLatin1Char('0')).arg(st.wSecond,2,10,QLatin1Char('0'));
};FILETIME * file=(FILETIME *) malloc(sizeof(FILETIME));
requiredSize= sizeof (FILETIME );PBYTE buffer=(PBYTE)file;if(GetSetupDiGetDeviceProperty(DeviceInfoSet,DeviceInfoData,propType ,&PropertyKey ,buffer,requiredSize)){QString  Values=FileTimeToString(*file);}

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

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

相关文章

数据结构——二叉树——堆

前言&#xff1a; 在前面我们已经学习了数据结构的基础操作&#xff1a;顺序表和链表及其相关内容&#xff0c;今天我们来学一点有些难度的知识——数据结构中的二叉树&#xff0c;今天我们先来学习二叉树中堆的知识&#xff0c;这部分内容还是非常有意思的&#xff0c;下面我们…

虚拟机Linux(centos)安装python3.8(超详细)

一、Python下载 下载地址&#xff1a;https://www.python.org/downloads/source/ 输入下面网址即可直接下载&#xff1a; python3.8&#xff1a;https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz python3.6&#xff1a;https://www.python.org/ftp/python/3.6.5/…

微信小程序(黑马优购:登录)

1.点击结算进行条件判断 user.js //数据 state: () >({ // address: {} address: JSON.parse(uni.getStorageSync(address) || {}), token: }), my-settle.vue computed: { ...mapGetters(m_cart,[checkedCount,total,checkedGoodsAmount]), …

IP种子是什么?理解和应用

在网络世界中&#xff0c;IP种子是一个广泛应用于文件共享和网络下载领域的概念。它是一种特殊的标识符&#xff0c;用于识别和连接到基于对等网络&#xff08;P2P&#xff09;协议的文件共享网络中的用户或节点。本文将深入探讨IP种子的含义、作用以及其在网络中的应用。 IP地…

【Linux】TCP网络套接字编程+守护进程

文章目录 日志类&#xff08;完成TCP/UDP套接字常见连接过程中的日志打印&#xff09;单进程版本的服务器客户端通信多进程版本和多线程版本守护进程化的多线程服务器 日志类&#xff08;完成TCP/UDP套接字常见连接过程中的日志打印&#xff09; 为了让我们的代码更规范化&…

瑞_23种设计模式_观察者模式

文章目录 1 观察者模式&#xff08;Observer Pattern&#xff09;1.1 介绍1.2 概述1.3 观察者模式的结构1.4 观察者模式的优缺点1.5 观察者模式的使用场景 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 JDK中提供的观察者模式实现 ★4.1 Observable类4.2 Obse…

Day63-LVS四层负载均衡及结合Nginx7层负载均衡实践

Day63-LVS四层负载均衡及结合Nginx7层负载均衡实践 1. LVS&#xff08;Linux Virtual Server&#xff09;介绍2. IPVS&#xff08;LVS&#xff09;发展史3. IPVS软件工作层次图4. LVS技术点小结5. LVS的4模式原理讲解5.1 NAT(Network AddressTranslation)&#xff0c;中文网络地…

《Retrieval-Augmented Generation for Large Language Models: A Survey》 AI 解读

论文链接&#xff1a;Retrieval-Augmented Generation for Large Language Models: A Survey 论文标题&#xff1a;《Retrieval-Augmented Generation for Large Language Models: A Survey》 一译中文版地址&#xff1a; https://yiyibooks.cn/arxiv/2312.10997v5/index.htm…

PI案例分享--2000A核心电源网络的设计、仿真与验证

目录 摘要 0 引言 1 为什么需要 2000A 的数字电子产品? 2 2000A 的供电电源设计 2.1 "MPM3698 2*MPM3699"的 MPS扩展电源架构 2.2 使用恒定导通时间(COT)模式输出核心电压的原因 2.3 模块化 VRM 的优势 2.4 用步进负载验证2000A的设计难点 2.4.1 电源网络 …

qtcreator的信号槽链接

在ui文件中简单创建一个信号槽连接并保存可以在ui_mainwindow.h下 class Ui_MainWindow 类 void setupUi(QMainWindow *MainWindow)函数 找到对应代码 QObject::connect(pushButton, SIGNAL(clicked()), MainWindow, SLOT(close())); 下拉&#xff0c;由于 class MainWind…

《权力》为什么只为某些人所拥有 - 三余书屋 3ysw.net

权力&#xff1a;为什么只为某些人所拥有 大家好&#xff0c;今天我们解读的书名是《权力》&#xff0c;副标题是“为什么只为某些人所拥有”。该书深入探讨了职场中的权力议题&#xff0c;强调获得权力是关键的职场技能之一。在激烈的职场竞争中&#xff0c;缺乏这一技能将使…

C#(winform) 调用MATLAB函数

测试环境 VisualStudio2022 / .NET Framework 4.7.2 Matlab2021b 参考&#xff1a;C# Matlab 相互调用 Matlab 1、编写Matlab函数 可以没有任何参数单纯定义matlab处理的函数&#xff0c;输出的数据都存在TXT中用以后期读取数据 function [result,m,n] TEST(list) % 计算…

Python 后端 Flask 使用 Flask-SocketIO、前端 Vue3 实现长连接 Websocket 通信详细教程(更新中)

Flask 安装 Flask-Socketio Flask-SocketIO 第三方库使 Flask 应用程序可以实现客户端和服务器之间的低延迟双向通信。客户端应用程序可以使用 Javascript、Python、C、Java 和 Swift 中的任何 SocketIO 客户端库或任何其他兼容客户端来建立与服务器的永久连接。 Flask-Socke…

逐步学习Go-Select多路复用

概述 这里又有多路复用&#xff0c;但是Go中的这个多路复用不同于网络中的多路复用。在Go里&#xff0c;select用于同时等待多个通信操作&#xff08;即多个channel的发送或接收操作&#xff09;。Go中的channel可以参考我的文章&#xff1a;逐步学习Go-并发通道chan(channel)…

使用 Yoda 和 ClickHouse 进行实时欺诈检测

背景 Instacart 是北美领先的在线杂货公司,拥有数百万活跃的客户和购物者。在其平台上打击欺诈和滥用行为不仅对于维护一个值得信赖和安全的环境至关重要,也对保持Instacart的财务健康至关重要。在这篇文章中,将介绍了一个欺诈平台——Yoda,解释了为什么我们选择ClickHous…

【踩坑】荣耀系统Android8.0 system目录Read-only file system

本来以为直接把Charles证书改成系统证书格式&#xff0c;然后通过mt管理器root之后移动到系统证书目录就行了&#xff0c;结果访问baidu仍然显示网络错误&#xff0c;折腾一晚上。后来直接安装为用户证书&#xff0c;与系统证书冲突。 手机型号&#xff1a;荣耀v10 EMUI&…

升级程序到Java21的记录一(在先升级jdk到21)

背景&#xff1a;为了使用Java21的最新特性虚拟线程以及提高程序的整体性能&#xff0c;决定将一个程序A升级到Java21. 备注&#xff1a;程序A有很多文件操作因此使用虚拟线程对提升性能有帮助&#xff0c;如果读者的程序是其他类型&#xff0c;请参考虚拟线程的一些资料决定是…

STM32学习笔记(10_3)- 软件I2C读写MPU6050

无人问津也好&#xff0c;技不如人也罢&#xff0c;都应静下心来&#xff0c;去做该做的事。 最近在学STM32&#xff0c;所以也开贴记录一下主要内容&#xff0c;省的过目即忘。视频教程为江科大&#xff08;改名江协科技&#xff09;&#xff0c;网站jiangxiekeji.com 本期开…

flutter官方案例context_menus

1&#xff1a;根据项目中的案例进行部署 2&#xff1a;运行查看有什么用&#xff0c;可不可以直接复制粘贴 案例地址 https://github.com/flutter/samples/tree/main/context_menus案例展示方法 直接把这个文件夹中的文件复制到lib文件夹中 3&#xff0c;19&#xff0c;4的fl…

Lazarus远控组件NukeSped分析

静态信息&#xff1a; 样本md5&#xff1a;9b656f5d7e679b94e7b91fc3c4f313e4 由此可见为假的Adobe Flash Player 的攻击样本 样本分析 通过五个函数&#xff0c;内部调用sub_40159D函数动态获取API函数 利用IDA python解密字符串。。 完整python代码 Python> idc.get_…