当前位置: 首页 > news >正文

【Delphi】操纵EXE文件中版本信息(RT_VERSION)

RT_VERSION 是 Windows 可执行文件中用于存储版本信息的重要资源类型,它包含了应用程序的版本号、公司信息、版权声明等元数据。

基本概念

RT_VERSION 资源类型的 ID 为 16(0x10),它采用层次化的结构组织版本信息,主要包含以下几个部分:

  • VS_VERSIONINFO:顶层结构,包含固定版本信息和子结构
  • VS_FIXEDFILEINFO:固定格式的版本信息,与语言无关
  • VarFileInfo:存储语言和代码页信息
  • StringFileInfo:存储用户可读的字符串版本信息

数据结构定义

VS_VERSIONINFO 结构

typedef struct {WORD             wLength;          // 整个结构的长度(字节)WORD             wValueLength;     // VS_FIXEDFILEINFO 的长度WORD             wType;            // 资源类型(1 表示文本数据)WCHAR            szKey[16];        // 关键字 "VS_VERSION_INFO"WORD             Padding1;         // 对齐填充VS_FIXEDFILEINFO Value;            // 固定版本信息WORD             Padding2;         // 对齐填充WORD             Children;         // 子结构数量(通常为 2)
} VS_VERSIONINFO, *LPVS_VERSIONINFO;

VS_FIXEDFILEINFO 结构

typedef struct {DWORD   dwSignature;          // 签名,固定为 0xFEEF04BDDWORD   dwStrucVersion;       // 结构版本号(高字为主版本,低字为次版本)DWORD   dwFileVersionMS;      // 文件版本号(高 32 位)DWORD   dwFileVersionLS;      // 文件版本号(低 32 位)DWORD   dwProductVersionMS;   // 产品版本号(高 32 位)DWORD   dwProductVersionLS;   // 产品版本号(低 32 位)DWORD   dwFileFlagsMask;      // 文件标志掩码DWORD   dwFileFlags;          // 文件标志DWORD   dwFileOS;             // 目标操作系统DWORD   dwFileType;           // 文件类型DWORD   dwFileSubtype;        // 文件子类型DWORD   dwFileDateMS;         // 文件创建日期(高 32 位)DWORD   dwFileDateLS;         // 文件创建日期(低 32 位)
} VS_FIXEDFILEINFO, *LPVS_FIXEDFILEINFO;

VarFileInfo 结构

typedef struct {WORD  wLength;          // 结构总长度WORD  wValueLength;     // 始终为 0WORD  wType;            // 资源类型(1 表示文本数据)WCHAR szKey[10];        // 关键字 "VarFileInfo"WORD  Padding;          // 对齐填充// 包含语言和代码页信息的子结构
} VarFileInfo, *LPVarFileInfo;

StringFileInfo 结构

typedef struct {WORD  wLength;          // 结构总长度WORD  wValueLength;     // 始终为 0WORD  wType;            // 资源类型(1 表示文本数据)WCHAR szKey[13];        // 关键字 "StringFileInfo"WORD  Padding;          // 对齐填充// 包含特定语言代码页的字符串信息块
} StringFileInfo, *LPStringFileInfo;

StringTable 结构

typedef struct {WORD  wLength;          // 结构总长度WORD  wValueLength;     // 始终为 0WORD  wType;            // 资源类型(1 表示文本数据)WCHAR szKey[8];         // 语言代码页标识符(如 "040904B0")WORD  Padding;          // 对齐填充// 包含多个版本信息字符串
} StringTable, *LPStringTable;

String 结构

typedef struct {WORD  wLength;          // 字符串结构总长度WORD  wValueLength;     // 字符串值的长度(字节)WORD  wType;            // 资源类型(1 表示文本数据)WCHAR szKey[];          // 字符串名称(如 "CompanyName")WORD  Padding;          // 对齐填充WCHAR Value[];          // 字符串值
} String, *LPString;

重要枚举值

文件标志 (dwFileFlags)

VS_FF_DEBUG        = $00000001;  // 包含调试信息
VS_FF_PRERELEASE   = $00000002;  // 预发布版本
VS_FF_PATCHED      = $00000004;  // 已修补的文件
VS_FF_PRIVATEBUILD = $00000008;  // 私有构建版本
VS_FF_INFOINFERRED = $00000010;  // 信息推断而来
VS_FF_SPECIALBUILD = $00000020;  // 特殊构建版本

目标操作系统 (dwFileOS)

VOS_UNKNOWN        = $00000000;  // 未知操作系统
VOS_DOS            = $00010000;  // MS-DOS
VOS_NT             = $00040000;  // Windows NT
VOS__WINDOWS16     = $00000001;  // 16位Windows
VOS__WINDOWS32     = $00000004;  // 32位Windows
VOS_NT_WINDOWS32   = $00040004;  // Windows NT 32位

文件类型 (dwFileType)

VFT_UNKNOWN        = $00000000;  // 未知类型
VFT_APP            = $00000001;  // 应用程序
VFT_DLL            = $00000002;  // 动态链接库
VFT_DRV            = $00000003;  // 设备驱动程序
VFT_FONT           = $00000004;  // 字体文件
VFT_VXD            = $00000005;  // VxD驱动程序
VFT_STATIC_LIB     = $00000007;  // 静态链接库

版本信息字符串

StringFileInfo 中可以包含以下标准字符串:

字符串名称说明
Comments备注信息
CompanyName公司名称
FileDescription文件描述
FileVersion文件版本字符串
InternalName内部名称
LegalCopyright版权信息
LegalTrademarks商标信息
OriginalFilename原始文件名
PrivateBuild私有构建信息
ProductName产品名称
ProductVersion产品版本字符串
SpecialBuild特殊构建信息

Delphi 中处理 RT_VERSION 的示例代码

读取版本信息

usesWindows, SysUtils, Classes;function GetFileVersionInfo(const FileName: string): string;
varhFile: DWORD;dwSize: DWORD;pData: Pointer;pFixedInfo: PVS_FIXEDFILEINFO;dwVerSize: DWORD;FileVerMS, FileVerLS: DWORD;ProductVerMS, ProductVerLS: DWORD;
beginResult := '';// 获取版本信息大小dwSize := GetFileVersionInfoSize(PChar(FileName), hFile);if dwSize = 0 then Exit;// 分配内存并读取版本信息GetMem(pData, dwSize);tryif GetFileVersionInfo(PChar(FileName), 0, dwSize, pData) thenbegin// 获取固定版本信息if VerQueryValue(pData, '\', Pointer(pFixedInfo), dwVerSize) thenbeginFileVerMS := pFixedInfo.dwFileVersionMS;FileVerLS := pFixedInfo.dwFileVersionLS;ProductVerMS := pFixedInfo.dwProductVersionMS;ProductVerLS := pFixedInfo.dwProductVersionLS;Result := Format('文件版本: %d.%d.%d.%d'#13#10 +'产品版本: %d.%d.%d.%d',[HIWORD(FileVerMS), LOWORD(FileVerMS),HIWORD(FileVerLS), LOWORD(FileVerLS),HIWORD(ProductVerMS), LOWORD(ProductVerMS),HIWORD(ProductVerLS), LOWORD(ProductVerLS)]);end;end;finallyFreeMem(pData);end;
end;function GetStringFileInfo(const FileName, ValueName: string): string;
varhFile: DWORD;dwSize: DWORD;pData: Pointer;pValue: PChar;dwValueSize: DWORD;LangID: array[0..1] of WORD;LangCode: string;
beginResult := '';// 获取版本信息大小dwSize := GetFileVersionInfoSize(PChar(FileName), hFile);if dwSize = 0 then Exit;// 分配内存并读取版本信息GetMem(pData, dwSize);tryif GetFileVersionInfo(PChar(FileName), 0, dwSize, pData) thenbegin// 获取语言IDif VerQueryValue(pData, '\VarFileInfo\Translation', Pointer(LangID), dwValueSize) thenbegin// 构建语言代码页路径LangCode := Format('\StringFileInfo\%.4x%.4x\%s', [LangID[0], LangID[1], ValueName]);// 获取字符串值if VerQueryValue(pData, PChar(LangCode), Pointer(pValue), dwValueSize) thenbeginResult := StrPas(pValue);end;end;end;finallyFreeMem(pData);end;
end;

更新版本信息

procedure UpdateFileVersionInfo(const FileName, NewVersion: string);
varhUpdate: THandle;VersionInfo: TMemoryStream;VersionData: array of Byte;VersionSize: DWORD;LangID: array[0..1] of WORD;LangCode: string;
begin// 创建新版本信息数据VersionInfo := TMemoryStream.Create;try// 这里需要构建完整的VS_VERSIONINFO结构// 实际应用中需要根据NewVersion参数构建正确的版本信息VersionSize := VersionInfo.Size;SetLength(VersionData, VersionSize);VersionInfo.Position := 0;VersionInfo.ReadBuffer(VersionData[0], VersionSize);// 开始更新资源hUpdate := BeginUpdateResource(PChar(FileName), False);if hUpdate = 0 thenRaiseLastOSError;try// 更新RT_VERSION资源if not UpdateResource(hUpdate, RT_VERSION, MAKEINTRESOURCE(1),MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), @VersionData[0], VersionSize) thenRaiseLastOSError;// 完成更新if not EndUpdateResource(hUpdate, False) thenRaiseLastOSError;exceptEndUpdateResource(hUpdate, True);raise;end;finallyVersionInfo.Free;end;
end;

完整的版本信息读取示例

procedure ShowFileVersionInfo(const FileName: string);
varVersionInfo: string;CompanyName: string;FileDescription: string;LegalCopyright: string;ProductName: string;
beginVersionInfo := GetFileVersionInfo(FileName);if VersionInfo = '' thenbeginWriteln('无法读取版本信息');Exit;end;CompanyName := GetStringFileInfo(FileName, 'CompanyName');FileDescription := GetStringFileInfo(FileName, 'FileDescription');LegalCopyright := GetStringFileInfo(FileName, 'LegalCopyright');ProductName := GetStringFileInfo(FileName, 'ProductName');Writeln('版本信息:');Writeln(VersionInfo);Writeln('公司名称: ', CompanyName);Writeln('文件描述: ', FileDescription);Writeln('版权信息: ', LegalCopyright);Writeln('产品名称: ', ProductName);
end;

RC 文件中的版本信息定义

1 VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
BEGINBLOCK "VarFileInfo"BEGINVALUE "Translation", 0x0804, 0x04B0  // 简体中文, UnicodeENDBLOCK "StringFileInfo"BEGINBLOCK "080404B0"BEGINVALUE "Comments", "这是一个示例应用程序"VALUE "CompanyName", "我的公司"VALUE "FileDescription", "示例应用程序"VALUE "FileVersion", "1.0.0.1"VALUE "InternalName", "SampleApp"VALUE "LegalCopyright", "© 2025 我的公司. 保留所有权利."VALUE "LegalTrademarks", "SampleApp"VALUE "OriginalFilename", "SampleApp.exe"VALUE "PrivateBuild", ""VALUE "ProductName", "SampleApp"VALUE "ProductVersion", "1.0.0.1"VALUE "SpecialBuild", ""ENDEND
END

关键要点

  1. 资源 ID 要求:RT_VERSION 资源的 ID 必须为 1,否则 Windows 资源管理器无法正确显示版本信息
  2. 对齐要求:所有结构必须在 DWORD 边界上对齐
  3. 多语言支持:通过 VarFileInfo 和多个 StringTable 可以支持多种语言的版本信息
  4. 版本号格式:版本号由 4 个 16 位整数组成,格式为 Major.Minor.Build.Revision
  5. 字符串编码:所有字符串必须使用 Unicode 编码
  6. API 函数:使用 GetFileVersionInfo、VerQueryValue 等 API 函数读取版本信息

理解 RT_VERSION 格式对于版本控制、软件部署和系统集成等任务非常重要,它提供了一种标准化的方式来存储和检索应用程序的元数据。

http://www.dtcms.com/a/540232.html

相关文章:

  • 一周新闻热点事件seo 哪些媒体网站可以发新闻
  • Vue3的Pinia详解
  • 移动端性能监控探索:可观测 Android 采集探针架构与实现
  • OSS文件上传错误No buffer space available
  • 搜狐视频网站联盟怎么做企业网站优化的方式
  • c 网站做微信支付功能济源建设工程管理处网站
  • Visual Studio 编译带显卡加速的 OpenCV
  • 【EDA软件】【文件合并烧录操作方法】
  • Termux 部署 NextCloude 私人云盘,旧手机变云盘
  • 【优选算法】DC-Mergesort-Harmonies:分治-归并的算法之谐
  • WPF 控件速查 PDF 笔记(可直接落地版)(带图片)
  • 淘宝实时拍立淘按图搜索数据|商品详情|数据分析提取教程
  • WinCC的CS架构部署
  • 房地产店铺首页设计过程门户网站优化报价
  • 河南建设安全监督网站WordPress集成tipask
  • Taro 自定义tab栏和自定义导航栏
  • 辛格迪客户案例 | 迈威生物电子合约(eSignDMS)项目
  • 《微信小程序》第七章:TabBar设计
  • 国外做外链常用的网站网站 建设 网站设计公司
  • Flutter package 内部加载该包的 assets 时,需要使用 packages/ 前缀
  • 5 种简单方法将文件从 Mac 传输到 iPhone
  • ETH, Lwip,Tcp之间关系
  • 神经网络之向量相似性
  • 关于前端文件处理-实战篇
  • <script setup lang=“ts“>+uniapp实现轮播(swiper)效果
  • 网站建设与设计方案现在什么网页游戏最好玩最火
  • SOME/IP 序列化问题
  • 【Rust编程:从新手到大师】 Rust 所有权与内存安全
  • wordpress如何添加背景音乐seo点评类网站
  • Flink Keyed State 详解之二