QT获取dll库文件详细信息
一、需求背景
获取软件下依赖的dll库的版本信息,如下图所示版本为1.0.7.1018

二、实现方法
2.1步骤
windows下实现,基于version.lib(version.dll)提供的函数获取这些信息
首先使用GetFileVersionInfoSizeA(W)获取VersionInfo的大小,申请缓冲区;
接着使用GetFileVersionInfoA(W)获取VersionInfo数据到缓冲区;
接着使用VerQueryValueA(W)依次获取\,\VarFileInfo\Translation,再根据Translation获取语言类型,接着\VarFileInfo\080404B0\ProductVersion便获取到了版本信息。
参考:https://www.cnblogs.com/comor/p/10607383.html
2.2 源码
#include <QDebug>
#include <string>
#include <tchar.h>
#include <iostream>
#include <windows.h>BOOL GetFileInfoStringWinApi(LPCTSTR pFileName, LPCTSTR pName /* = NULL */, LPTSTR ptBuf, UINT lenBuf)
{DWORD dwDummyHandle = 0; // will always be set to zeroDWORD dwLen = 0;BYTE *pVersionInfo = NULL;BOOL bRetVal;VS_FIXEDFILEINFO FileVersion;HMODULE hVerDll;hVerDll = LoadLibrary(_T("VERSION.dll"));if (hVerDll == NULL){return FALSE;}#ifdef _UNICODEtypedef DWORD(WINAPI * Fun_GetFileVersionInfoSize)(LPCTSTR, DWORD *);typedef BOOL(WINAPI * Fun_GetFileVersionInfo)(LPCTSTR, DWORD, DWORD, LPVOID);typedef BOOL(WINAPI * Fun_VerQueryValue)(LPCVOID, LPCTSTR, LPVOID, PUINT);
#elsetypedef DWORD(WINAPI * Fun_GetFileVersionInfoSize)(LPCSTR, DWORD *);typedef BOOL(WINAPI * Fun_GetFileVersionInfo)(LPCSTR, DWORD, DWORD, LPVOID);typedef BOOL(WINAPI * Fun_VerQueryValue)(LPCVOID, LPCSTR, LPVOID, PUINT);
#endifFun_GetFileVersionInfoSize pGetFileVersionInfoSize;Fun_GetFileVersionInfo pGetFileVersionInfo;Fun_VerQueryValue pVerQueryValue;#ifdef _UNICODEpGetFileVersionInfoSize = (Fun_GetFileVersionInfoSize)::GetProcAddress(hVerDll, "GetFileVersionInfoSizeW");pGetFileVersionInfo = (Fun_GetFileVersionInfo)::GetProcAddress(hVerDll, "GetFileVersionInfoW");pVerQueryValue = (Fun_VerQueryValue)::GetProcAddress(hVerDll, "VerQueryValueW");
#elsepGetFileVersionInfoSize = (Fun_GetFileVersionInfoSize)::GetProcAddress(hVerDll, "GetFileVersionInfoSizeA");pGetFileVersionInfo = (Fun_GetFileVersionInfo)::GetProcAddress(hVerDll, "GetFileVersionInfoA");pVerQueryValue = (Fun_VerQueryValue)::GetProcAddress(hVerDll, "VerQueryValueA");
#endifstruct TRANSLATION{WORD langID; // language IDWORD charset; // character set (code page)} Translation;Translation.langID = 0x0409; //Translation.charset = 1252; // default = ANSI code pagedwLen = pGetFileVersionInfoSize(pFileName, &dwDummyHandle);if (dwLen == 0){bRetVal = FALSE;goto End;}pVersionInfo = new BYTE[dwLen]; // allocate version infobRetVal = pGetFileVersionInfo(pFileName, 0, dwLen, pVersionInfo);if (bRetVal == FALSE){goto End;}VOID *pVI;UINT uLen;bRetVal = pVerQueryValue(pVersionInfo, _T("\\"), &pVI, &uLen);if (bRetVal == FALSE){goto End;}memcpy(&FileVersion, pVI, sizeof(VS_FIXEDFILEINFO));bRetVal = pVerQueryValue(pVersionInfo, _T("\\VarFileInfo\\Translation"),&pVI, &uLen);if (bRetVal && uLen >= 4){memcpy(&Translation, pVI, sizeof(TRANSLATION));}else{bRetVal = FALSE;goto End;}// BREAKIF(FileVersion.dwSignature != VS_FFI_SIGNATURE);if (FileVersion.dwSignature != VS_FFI_SIGNATURE){bRetVal = FALSE;goto End;}VOID *pVal;UINT iLenVal;if (pName == NULL){_stprintf_s(ptBuf, lenBuf, _T("%d.%d.%d.%d"),HIWORD(FileVersion.dwFileVersionMS), LOWORD(FileVersion.dwFileVersionMS),HIWORD(FileVersion.dwFileVersionLS), LOWORD(FileVersion.dwFileVersionLS));}else{TCHAR szQuery[1024];_stprintf_s(szQuery, 1024, _T("\\StringFileInfo\\%04X%04X\\%s"),Translation.langID, Translation.charset, pName);bRetVal = pVerQueryValue(pVersionInfo, szQuery, &pVal, &iLenVal);if (bRetVal){_stprintf_s(ptBuf, lenBuf, _T("%s"), (TCHAR *)pVal);}else{_stprintf_s(ptBuf, lenBuf, _T("%s"), _T(""));}}End:FreeLibrary(hVerDll);hVerDll = NULL;delete[] pVersionInfo;pVersionInfo = NULL;return bRetVal;
}bool GetFileInfoString(const QString &fileName, const QString &name, QString &value)
{TCHAR *ptszStr = NULL;ptszStr = new TCHAR[1024];LPCWSTR fileName_wstr = reinterpret_cast<LPCWSTR>(fileName.data());LPCWSTR name_wstr = reinterpret_cast<LPCWSTR>(name.data());BOOL bRet = GetFileInfoStringWinApi(fileName_wstr, name_wstr, ptszStr, 1024);value = QString::fromWCharArray(ptszStr);delete ptszStr;ptszStr = NULL;return bRet;
}QString GetFileProductVersion(const QString &fileName)
{QString version;GetFileInfoString(fileName, "ProductVersion", version);return version;
}2.3 测试结果
int main(int argc, char *argv[])
{QString fileName = "xxx//CZVisionCameraOperator.dll";qDebug() << GetFileProductVersion(fileName);return 0;
}
2.4 扩展
除版本信息,还可以获取文件说明、产品名称、版权、公司名称、原始文件名称等
FileDescription 文件说明
FileVersion 文件版本
ProductName 产品名称
ProductVersion 产品版本
LegalCopyright 版权
CompanyName 公司名称
OriginalFilename 原始文件名
相关文章:
QT获取dll库文件详细信息
一、需求背景获取软件下依赖的dll库的版本信息,如下图所示版本为1.0.7.1018二、实现方法2.1步骤windows下实现,基于version.lib(version.dll)提供的函数获取这些信息首先使用GetFileVersionInfoSizeA(W)获取VersionInfo的大小,申请缓冲区&…...
常见的电脑运行卡顿原因及解决方法
大家在日常使用电脑过程中,会发现多开几个文件就卡顿,其实很多时候都跟C盘长期不清理有关,C盘的内存被下载的软件安装包、页面文件、休眠文件、更新文件等一系列的文件占据。大的文件甚至能占到20-30G,驱动人生就为大家带来几种解…...
案例08-让软件的使用者成为软件的设计者
一:背景介绍 对于需求的开发每天可能都会有上线的情况,为了防止每次上线拉取代码或者修改配置而引发的冲突以及发生了冲突应该找谁一起确定一下代码留下那一部分的情况。所以在开发的群中会有一个表格来记录每个需求上线修改的环境、是否修改数据库、是否…...
QinQ与Vlan Mapping讲解
目录 QinQ Vlan扩展 QinQ实现方式 QinQ实验配置 Vlan Mapping Vlan映射 映射方式 配置命令 QinQ Vlan扩展 QinQ全称为802.1Q-in-802.1Q,为Vlan扩展技术,在802.1Q标签报文的基础上再增加一层802.1Q标签,实现扩展Vlan空间;可…...
golang 获取token方法
package main import ( "fmt" "time" "github.com/dgrijalva/jwt-go" ) const ( SECRETKEY "202203021124355xxx" //私钥 ) // 自定义 Claims type CustomClaims struct { UserId int64 jwt.StandardClaims } func main() { //生…...
【数据库专题】数据库Mongodb之深入认知云计算三种服务方式、mongodb特点、mongodb重要进程 mongod、mongo、其他进程区别
文章目录一、什么是云计算1. IaaS:基础设施即服务2. SaaS:软件即服务3. PaaS:平台即服务二、大数据与云计算关系三、什么是MongoDB四、大数据与MongoDB五、MongoDB特点六、安装MongoDB七、重要进程介绍7.1 mongod进程7.2 mongo进程7.3 其他进程7.3.1 mongodump重建数据库7.3.2 …...
ccc-pytorch-小实验合集(4)
文章目录一、 Himmelblau 优化二、多分类实战-Mnist三、Sequential与CPU加速-Mnist四、visidom可视化一、 Himmelblau 优化 Himmelblau 是一个具有4个最优值的2维目标函数。其函数和最优值点如下: 图象绘制: import numpy as np from matplotlib impo…...
webrtc音频系列——4、RTP与RTCP协议
如果让你从0开发一套实时互动直播系统,你首先要选择网络传输协议。UDP 还是 TCP?答案是:UDP。为什么实时传输不能用 TCP ?TCP 的目的就是实现数据的可靠传输,因此他有一套 握手,发送 -> 确认,…...
C++枚举解读(enum)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、枚举是什么?二、使用步骤1.作用域2.隐式类型转换3.显式指定枚举值类型4.指定枚举值的值4.整形显式转换成枚举总结前言 对于开发C来说࿰…...
OSCP-课外5(Web图片泄露服务信息、日志中毒)
目录 一、主机发现与端口扫描 二、Web信息收集 三、系统信息收集与提权 一、主机发现与端口扫描...
汇编指令学习(ADD,SUB,MUL,DIV,XADD,INC,DEC,NEG)
一、ADD加法操作指令将eax置1,ebx置2,运行下面命令,将结果保存到eaxadd eax,ebx扩展:adc需要再加上CF标志位的值adc eax,ebx二、SUB减法操作指令将eax置3,ebx置2,运行下面命令,将结果…...
【电源专题】案例:充电芯片损坏为什么判断是从NTC进入的EOS
最近有发现一个异常就是测试部测试测试然后充电芯片就无法使用了。通过二极管特性分析(参考文章:电源专题】案例:电源芯片厂家怎么判断电源芯片端口是否损坏)是NTC管脚已经损坏对地短路了。但是以前没有发现这个问题,最近更换了芯片后就发现的特别明显。 首先分析一下现在…...
C语言中的数据储存规则
写在开头 关于复习的相关内容其实从一开始就列出了大纲,但是迟迟没有开始复习,一方面是因为学校学业却是繁忙,另一方面还是内心对旧知识掌握不熟练需要再学一遍的畏惧和懒惰,但如今,复习必须开始了。今天我从C语言的最…...
Android kotlin实战之协程suspend详解与使用
前言 Kotlin 是一门仅在标准库中提供最基本底层 API 以便各种其他库能够利用协程的语言。与许多其他具有类似功能的语言不同,async 与 await 在 Kotlin 中并不是关键字,甚至都不是标准库的一部分。此外,Kotlin 的 挂起函数 概念为异步操作提供…...
Pycharm中的Virtualenv Environment、Conda Environment
版本一 Conda Environment该不该选? 先说结论,该选,而且还是正解。前提是你打算"用Anaconda来管理各种Python环境,同时管理Python下面的各种包"。 选了Conda Environment意味着什么? 意味着你以后如果要装新的包的话…...
C++容器介绍:vector
目录vector简介使用方法1.头文件2.vector声明及初始化3.vector基本操作(1). 容量(2). 修改(3)迭代器(4)元素的访问(5)算法vector 简介 vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vecto…...
抗锯齿和走样(笔记)
Artifacts(瑕疵): 比如人眼采样频率跟不上陀螺的旋转速度,这时就有可能看到陀螺在反方向旋转怎么做抗锯齿(滤波): 在采样之前先进行一个模糊操作,可以降低锯齿的明显程度 通过傅里叶…...
线程池的使用——线程池的创建方式
线程池的使用——创建线程线程池的创建线程池的创建方式Executors.newFixedThreadPool:Executors.newCachedThreadPool:Executors.newSingleThreadExecutor:Executors.newScheduledThreadPool:Executors.newSingleThreadScheduled…...
代码随想录算法训练营day47 |动态规划 198打家劫舍 213打家劫舍II 337打家劫舍III
day47198.打家劫舍1.确定dp数组(dp table)以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组213.打家劫舍II情况一:考虑不包含首尾元素情况二:考虑包含首元素,不包含尾元素情况三&#x…...
项目设计模式和规范
1、责任链模式 自己的理解:避免发生方与接收方解耦 优点:①降低发送方与接收方的耦合 ②简化他们对象 ③方便扩展新增 处理者 缺点:①不方便排错 ②性能问题,且使用不当容易搞出死循环 应用场景:拦截器 Interceptor和过滤器 filter:符合模式的进行拦截或者过滤到,然…...
保姆级避坑指南:用GGCNN源码处理Cornell抓取数据集,解决tiff文件生成失败问题
GGCNN源码实战:Cornell数据集预处理深度排错指南 第一次运行GGCNN的Cornell数据集预处理脚本时,我盯着毫无反应的终端窗口足足等了十分钟——没有进度条,没有错误提示,只有光标在无情地闪烁。这大概是每个复现论文的开发者都会经历…...
中国半导体产业崛起:资本驱动下的存储器攻坚与全产业链布局
1. 行业格局的十字路口:当西方整合遇上东方崛起最近几年,半导体行业的头条新闻几乎被一系列重磅并购案所占据:恩智浦收购飞思卡尔、安华高并购博通、英特尔鲸吞阿尔特拉。这些动辄数百亿美元的巨无霸交易,背后传递出一个清晰的信号…...
Apollo Save Tool:3步解决PlayStation存档管理难题的终极方案
Apollo Save Tool:3步解决PlayStation存档管理难题的终极方案 【免费下载链接】apollo-ps4 Apollo Save Tool (PS4) 项目地址: https://gitcode.com/gh_mirrors/ap/apollo-ps4 你是否曾为丢失珍贵的游戏进度而懊恼?是否在主机升级时面临数百个存档…...
马斯克诉奥尔特曼案第三周:微软与 OpenAI 举证反击,争议焦点浮出水面
【案件进展概述】智东西 5 月 12 日消息,今天,马斯克诉奥尔特曼案进入第三周,被告方关键证人相继出庭,微软 CEO 萨提亚纳德拉 (Satya Nadella)、OpenAI 联合创始人兼前首席科学家 伊利亚苏茨克维 ÿ…...
从布朗运动到伊藤公式:金融随机世界的建模基石
1. 从花粉运动到股票价格:布朗运动的金融启示 1827年,英国植物学家罗伯特布朗在显微镜下观察到花粉颗粒在水中的不规则舞动,这个看似简单的物理现象却在80年后被爱因斯坦用数学语言精确描述。有趣的是,当我们将显微镜换成股票行情…...
Java开发者集成OpenAI API:社区SDK核心设计与生产实践
1. 项目概述:一个面向Java开发者的OpenAI API集成利器如果你是一名Java后端开发者,最近被ChatGPT、DALLE这些AI能力深深吸引,想在自家的Spring Boot应用里快速集成智能对话、文本生成或者图像创作功能,那你大概率已经搜过“OpenAI…...
告别预装旧版Demo:详解mmWave SDK两种刷写模式(Demonstration vs. CCS Development)及适用场景
告别预装旧版Demo:详解mmWave SDK两种刷写模式(Demonstration vs. CCS Development)及适用场景 当你第一次拿到毫米波雷达评估模块(EVM)时,预装的Demo固件可能已经过时半年甚至更久。这时候你会面临一个关键…...
构建个人技能知识库:从Markdown管理到自动化实践
1. 项目概述:一个技能库的诞生与价值最近在整理个人知识体系时,我一直在思考一个问题:如何将那些零散的、跨领域的“技能点”系统化地管理起来,形成一个可以持续迭代、随时取用的个人工具箱?这不仅仅是写一份简历上的技…...
PCB高级工艺如何降本:盲孔、微孔与HDI设计的成本优化实战
1. 项目概述:当高级PCB技术成为降本利器在硬件研发圈子里待久了,总有一个根深蒂固的印象:但凡沾上“高级”、“高密度”这些词的技术,比如盲孔、埋孔和微孔,那成本肯定是蹭蹭往上涨。我刚开始接触HDI板设计时也是这么想…...
如何用自动化脚本解放双手:淘宝淘金币全任务一键完成指南
如何用自动化脚本解放双手:淘宝淘金币全任务一键完成指南 【免费下载链接】taojinbi 淘宝淘金币自动执行脚本,包含蚂蚁森林收取能量,芭芭农场全任务,解放你的双手 项目地址: https://gitcode.com/gh_mirrors/ta/taojinbi 还…...
