
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; // 签名,固定为 0xFEEF04BD
DWORD 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; // 始终为 0
WORD wType; // 资源类型(1 表示文本数据)
WCHAR szKey[10]; // 关键字 "VarFileInfo"
WORD Padding; // 对齐填充
// 包含语言和代码页信息的子结构
} VarFileInfo, *LPVarFileInfo;
StringFileInfo 结构
typedef struct {
WORD wLength; // 结构总长度
WORD wValueLength; // 始终为 0
WORD wType; // 资源类型(1 表示文本数据)
WCHAR szKey[13]; // 关键字 "StringFileInfo"
WORD Padding; // 对齐填充
// 包含特定语言代码页的字符串信息块
} StringFileInfo, *LPStringFileInfo;
StringTable 结构
typedef struct {
WORD wLength; // 结构总长度
WORD wValueLength; // 始终为 0
WORD 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 的示例代码
读取版本信息
uses
Windows, SysUtils, Classes;
function GetFileVersionInfo(const FileName: string): string;
var
hFile: DWORD;
dwSize: DWORD;
pData: Pointer;
pFixedInfo: PVS_FIXEDFILEINFO;
dwVerSize: DWORD;
FileVerMS, FileVerLS: DWORD;
ProductVerMS, ProductVerLS: DWORD;
begin
Result := '';
// 获取版本信息大小
dwSize := GetFileVersionInfoSize(PChar(FileName), hFile);
if dwSize = 0 then Exit;
// 分配内存并读取版本信息
GetMem(pData, dwSize);
try
if GetFileVersionInfo(PChar(FileName), 0, dwSize, pData) then
begin
// 获取固定版本信息
if VerQueryValue(pData, '\', Pointer(pFixedInfo), dwVerSize) then
begin
FileVerMS := 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;
finally
FreeMem(pData);
end;
end;
function GetStringFileInfo(const FileName, ValueName: string): string;
var
hFile: DWORD;
dwSize: DWORD;
pData: Pointer;
pValue: PChar;
dwValueSize: DWORD;
LangID: array[0..1] of WORD;
LangCode: string;
begin
Result := '';
// 获取版本信息大小
dwSize := GetFileVersionInfoSize(PChar(FileName), hFile);
if dwSize = 0 then Exit;
// 分配内存并读取版本信息
GetMem(pData, dwSize);
try
if GetFileVersionInfo(PChar(FileName), 0, dwSize, pData) then
begin
// 获取语言ID
if VerQueryValue(pData, '\VarFileInfo\Translation', Pointer(LangID), dwValueSize) then
begin
// 构建语言代码页路径
LangCode := Format('\StringFileInfo\%.4x%.4x\%s',
[LangID[0], LangID[1], ValueName]);
// 获取字符串值
if VerQueryValue(pData, PChar(LangCode), Pointer(pValue), dwValueSize) then
begin
Result := StrPas(pValue);
end;
end;
end;
finally
FreeMem(pData);
end;
end;
更新版本信息
procedure UpdateFileVersionInfo(const FileName, NewVersion: string);
var
hUpdate: 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 then
RaiseLastOSError;
try
// 更新RT_VERSION资源
if not UpdateResource(hUpdate, RT_VERSION, MAKEINTRESOURCE(1),
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
@VersionData[0], VersionSize) then
RaiseLastOSError;
// 完成更新
if not EndUpdateResource(hUpdate, False) then
RaiseLastOSError;
except
EndUpdateResource(hUpdate, True);
raise;
end;
finally
VersionInfo.Free;
end;
end;
完整的版本信息读取示例
procedure ShowFileVersionInfo(const FileName: string);
var
VersionInfo: string;
CompanyName: string;
FileDescription: string;
LegalCopyright: string;
ProductName: string;
begin
VersionInfo := GetFileVersionInfo(FileName);
if VersionInfo = '' then
begin
Writeln('无法读取版本信息');
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
BEGIN
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0804, 0x04B0 // 简体中文, Unicode
END
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404B0"
BEGIN
VALUE "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", ""
END
END
END
关键要点
- 资源 ID 要求:RT_VERSION 资源的 ID 必须为 1,否则 Windows 资源管理器无法正确显示版本信息
- 对齐要求:所有结构必须在 DWORD 边界上对齐
- 多语言支持:通过 VarFileInfo 和多个 StringTable 可以支持多种语言的版本信息
- 版本号格式:版本号由 4 个 16 位整数组成,格式为 Major.Minor.Build.Revision
- 字符串编码:所有字符串必须使用 Unicode 编码
- API 函数:使用 GetFileVersionInfo、VerQueryValue 等 API 函数读取版本信息
理解 RT_VERSION 格式对于版本控制、软件部署和系统集成等任务非常重要,它提供了一种标准化的方式来存储和检索应用程序的元数据。

被折叠的 条评论
为什么被折叠?



