
对于已经编译生成好的exe文件,可否修改文件的版本信息呢?答案是肯定的,微软提供了修改exe文件版本信息的API。
一、查看文件版本信息
在exe文件的图标上鼠标右键菜单选择【属性】,然后选择【详细信息】

就可以看到exe文件的相关版权、版本信息。
二、版本信息包括的项目如下
Delphi
TRT_VERSION = packed record
FileVersion_High : DWORD; //文件版本 VS_FIXEDFILEINFO
FileVersion_Low : DWORD; //文件版本 VS_FIXEDFILEINFO
ProductVersion_High : DWORD; //产品版本 VS_FIXEDFILEINFO
ProductVersion_Low : DWORD; //产品版本 VS_FIXEDFILEINFO
LangID : Word; //0x0409
CodePage : Word; //0x04E4
CompanyName : string; //公司名称
FileDescription : string;
FileVersion : string; //文件版本
InternalName : string; //内部名称
LegalCopyright : string;
LegalTrademarks : string;
OriginalFilename : string;
ProgramID : string;
ProductName : string;
ProductVersion : string; //产品版本
Comments : string; //注释
SpecialBuild : string; //特殊版本,一般不使用
PrivateBuild : string; //私有版本,一般不使用,为空
Assembly_Version : string; //DeepL中有用
end;
三、使用到的函数对象
Delphi
//操作exe文件版本信息的对象
TEXE_Version = class
private
// 辅助函数
class procedure WriteWideStringWithNull(Stream: TStream; const S: string);
class procedure WriteWord(Stream: TStream; W: Word);
class procedure WriteDWord(Stream: TStream; D: DWORD);
class procedure AlignStream4(Stream: TStream);
// Build VS_FIXEDFILEINFO structure (binary, little-endian)
class procedure WriteFixedFileInfo(Stream: TStream; rt_Version : TRT_VERSION; FileFlagsMask, FileFlags, FileOS, FileType, FileSubtype: DWORD);
// Build a StringTable child block: a sequence of key/value pairs
class procedure WriteStringTable(Stream: TStream; rt_Version : TRT_VERSION);
// Build VarFileInfo block with Translation (LANGID + CodePage)
class procedure WriteVarFileInfo(Stream: TStream; LangID, CodePage: Word);
// Build top-level VERSIONINFO block and return binary as TBytes
class function BuildVersionInfoBinary(const rt_Version: TRT_VERSION): TBytes;
// 将版本信息写入到exe文件中
class function Update_ExeVersion(const ExeFileName : string; LangID : Word; versionBytes : TBytes) : Boolean;
public
{ 辅助函数:将版本字符串转换为VS_FIXEDFILEINFO需要的DWORD对 文本:1.0.0.2 }
class procedure VersionStrToDWords(const Version: string; out VerMS, VerLS: DWORD);
class function DWordsToVersionStr(VerMS, VerLS: DWORD): string;
//读取exe文件的版本信息 2025-11-05 测试 OK
class function Read_exe_Version(exeFile : string; out rt_Version : TRT_VERSION; out errmsg : string) : Boolean;
//写入exe文件的版本信息
class function Write_exe_Version(exeFile : string; rt_Version : TRT_VERSION; out errmsg : string) : Boolean;
//保存 RT_VERSION 二进制流为文件
class function SaveRTVersionResource(const ExeFileName, OutputFileName: string): Boolean;
end;
1. 读取exe文件版本信息
使用函数:TEXE_Version.Read_exe_Version(ExeFileName,myRT_VERSION,errmsg)
Delphi
class function TEXE_Version.Read_exe_Version(exeFile: string;
out rt_Version: TRT_VERSION; out errmsg : string): Boolean;
var
hFile: DWORD;
dwSize: DWORD;
pData: ^Byte;
pValue: PChar;
dwValueSize: DWORD;
LangID: PByte;
pFixInfo : PByte;
LangCode: string;
begin
Result := False;
//初始化变量 rt_Version
FillChar(rt_Version, SizeOf(TRT_VERSION), 0);
//如果文件不存在
if not FileExists(exeFile) then
begin
errmsg := 'exe文件不存在!';
Exit;
end;
// 获取版本信息大小
dwSize := GetFileVersionInfoSize(PChar(exeFile), hFile);
if dwSize = 0 then
begin
errmsg := '当前exe文件版本内容为空错误或者格式不正确!';
Exit;
end;
// 分配内存并读取版本信息
GetMem(pData, dwSize);
try
if GetFileVersionInfo(PChar(exeFile), hFile, dwSize, pData) then
begin
// 获取 VS_FIXEDFILEINFO 中的版本信息
if VerQueryValue(pData, '\', Pointer(pFixInfo), dwValueSize) then
begin
Move((pFixInfo + 8)^,rt_Version.FileVersion_High,4);
Move((pFixInfo + 12)^,rt_Version.FileVersion_Low,4);
Move((pFixInfo + 16)^,rt_Version.ProductVersion_High,4);
Move((pFixInfo + 20)^,rt_Version.ProductVersion_Low,4);
end
else
begin
errmsg := '获取版本信息中VS_FIXEDFILEINFO出现错误!';
Exit(False);
end;
// 获取语言ID
if VerQueryValue(pData, '\VarFileInfo\Translation', Pointer(LangID), dwValueSize) then
begin
//获取语言代码等
Move(LangID[0],rt_Version.LangID,2);
Move(LangID[2],rt_Version.CodePage,2);
// 构建语言代码页路径
LangCode := Format('\StringFileInfo\%.2x%.2x%.2x%.2x\',
[LangID[1], LangID[0], LangID[3], LangID[2]]);
// 获取版本信息字符串值
if VerQueryValue(pData, PChar(LangCode + 'CompanyName'), Pointer(pValue), dwValueSize) then
rt_Version.CompanyName := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'FileDescription'), Pointer(pValue), dwValueSize) then
rt_Version.FileDescription := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'FileVersion'), Pointer(pValue), dwValueSize) then
rt_Version.FileVersion := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'InternalName'), Pointer(pValue), dwValueSize) then
rt_Version.InternalName := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'LegalCopyright'), Pointer(pValue), dwValueSize) then
rt_Version.LegalCopyright := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'LegalTrademarks'), Pointer(pValue), dwValueSize) then
rt_Version.LegalTrademarks := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'OriginalFilename'), Pointer(pValue), dwValueSize) then
rt_Version.OriginalFilename := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'ProgramID'), Pointer(pValue), dwValueSize) then
rt_Version.ProgramID := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'ProductName'), Pointer(pValue), dwValueSize) then
rt_Version.ProductName := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'ProductVersion'), Pointer(pValue), dwValueSize) then
rt_Version.ProductVersion := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'Comments'), Pointer(pValue), dwValueSize) then
rt_Version.Comments := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'SpecialBuild'), Pointer(pValue), dwValueSize) then
rt_Version.SpecialBuild := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'PrivateBuild'), Pointer(pValue), dwValueSize) then
rt_Version.PrivateBuild := StrPas(pValue);
if VerQueryValue(pData, PChar(LangCode + 'Assembly Version'), Pointer(pValue), dwValueSize) then
rt_Version.Assembly_Version := StrPas(pValue);
errmsg := '正确获取到版本信息!';
Exit(True);
//else
// RaiseLastOSError;
end
else
begin
errmsg := '获取版本信息中的语言标志出现错误!';
Exit(False);
end;
end
else
begin
errmsg := '获取版本信息出现错误!';
Exit(False);
end;
finally
FreeMem(pData);
end;
end;
2. 写入exe文件版本信息
使用函数:TEXE_Version.Write_exe_Version(ExeFileName,myRT_VERSION,errmsg)
Delphi
class function TEXE_Version.Write_exe_Version(exeFile: string;
rt_Version: TRT_VERSION; out errmsg: string): Boolean;
var
versionBytes : TBytes;
dwSize : DWORD;
hFile : THandle;
begin
Result := False;
//1. 检查文件有效性
//如果文件不存在
if not FileExists(exeFile) then
begin
errmsg := 'exe文件不存在!';
Exit;
end;
// 获取版本信息大小
dwSize := GetFileVersionInfoSize(PChar(exeFile), hFile);
if dwSize = 0 then
begin
errmsg := '当前exe文件版本内容为空错误或者格式不正确!';
Exit;
end;
//2. 构造 版本信息数据流
versionBytes := BuildVersionInfoBinary(rt_Version);
//3. 备份原来的文件
CopyFile(PChar(exeFile),PChar(exeFile + '.bak'), False);
//4. 将版本信息写入到 exefile 文件中
Result := Update_ExeVersion(exeFile, rt_Version.LangID, versionBytes);
end;