您可以在纯文本文件中创建VERSIONINFO 资源(例如,Versioninfo.rc)
1 VERSIONINFO
FILEVERSION 2,0,0,0
PRODUCTVERSION 2,0,0,0
FILEOS 0x4
FILETYPE 0x1
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4"
{
VALUE "CompanyName", "Your Company Name Here\0"
VALUE "FileDescription", "Your File Description Here\0"
VALUE "FileVersion", "2.0.0.0\0"
VALUE "InternalName", "Your Internal Name\0"
VALUE "LegalCopyright", "© Your Copyright Notice\0"
VALUE "LegalTrademarks", "Your Trademark Notice\0"
VALUE "OriginalFilename", "YourExeName\0"
VALUE "ProductName", "Your Product Name\0"
VALUE "ProductVersion", "2.0.0.0\0"
VALUE "Comments", "No Comments\0"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409 0x04E4
}
}
注意:如图所示,每个项目的末尾都需要 C 样式的空终止符 (\0),以便资源编译器正确终止字符串。否则,当您使用资源管理器显示可执行文件的版本信息时,您可能会得到乱码或部分连接的值。
在您的项目源文件中添加一行:
{$R VersionInfo.res VersionInfo.rc}
我建议将通用版本信息资源放入版本控制系统中的外部引用中,然后您可以将其检出到每个项目的文件夹中并轻松更新。
做一个项目->构建,你的版本信息嵌入到 .exe 中。您可以使用 Windows 资源管理器并查看应用的属性进行验证。
在 CodeNewsFast 档案的 Embarcadero Delphi 论坛中有几篇文章(一篇由我撰写,一篇由 Jim Fleming 回复)。我的是 [here],在这里,我将逐步描述如何在您的项目中使用预构建事件来更新我在上面发布的资源脚本中的版本号。
Jim 发布了一些回复,但大约有十几个帖子有一个可执行文件的源代码,该可执行文件可以从适用于他的预构建事件中调用。 (有些事情我会做不同的事情,比如让 IDE 在命令行上传递项目名称和位置;如何做到这一点在分步文章中进行了描述。我还将处理版本解析和递增方式不同,但基本应用程序是一个很好的起始位置。)
Embarcadero 的小组目前已关闭,但我也能够从 CodeNewsFast 检索 Jim 的代码,并且可以在此处重现:
肯,
多亏了你,我得到了它的工作。
以防万一其他人想实施此解决方案,您将在下面找到必要的步骤和辅助程序。
吉姆·弗莱明
A) 在您的项目目录或任何地方创建您的版本信息资源文件,使用以下内容
内容和文件扩展名 .rc:
// Note the \000 !!!! Here and elsewhere below !!!!
// C string terminator !!!
#define CONST_VERSION "4.1.1.1003\000"
1 VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEOS 0x4
FILETYPE 0x1
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4" // Will need changing if your language is not English and char-set not 1252 (multilingual).
{
VALUE "CompanyName", "Whatever\000"
VALUE "FileDescription", "Whatever\000"
VALUE "FileVersion", CONST_VERSION
VALUE "InternalName", "My Internal Name\000"
VALUE "LegalCopyright", "Copyright © whoever\000"
VALUE "LegalTrademarks", "\000"
VALUE "OriginalFileName", "If you wish\000"
VALUE "ProductName", "What pleases you\000"
VALUE "ProductVersion", CONST_VERSION
VALUE "Comments", "Anything you wish to add\000"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409 0x04E4
}
}
B) 在某个文件夹中创建一个新项目,只有模块的代码应该类似于:
unit FormIncrementBuildNumber;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls, System.IOUtils, System.StrUtils;
type
TIncrementBuildNumber = class(TForm)
IncrementingBuildNumberLabel: TLabel;
procedure FormShow (Sender: TObject);
procedure FormActivate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
IncrementBuildNumber: TIncrementBuildNumber;
implementation
{$R *.dfm}
procedure TIncrementBuildNumber.FormShow (Sender: TObject);
var
Resource_File_Contents: TStringList;
Full_File_Name_And_Path: string;
First_Line_Of_File: string;
Position_First_Dot: Integer;
Position_Second_Dot: Integer;
Position_Third_Dot: Integer;
Position_Trailing_Backslash: Integer;
Start_of_Build_Number: Integer;
Length_of_Build_Number: Integer;
Build_Number_In_ASCII: string;
Build_Number_Numeric: Integer;
Old_Resource_File_Name: string;
Success: Boolean;
begin
if (System.ParamCount <> 1) then
begin
ShowMessage ('Resource File name not in first command-line parameter.');
Exit;
end;
Full_File_Name_And_Path := System.ParamStr(1);
if (not TFile.Exists(Full_File_Name_And_Path, False)) then
begin
ShowMessage ('Resource file ' + Full_File_Name_And_Path +
' not found.');
Exit;
end;
Resource_File_Contents := TStringList.Create;
try
Resource_File_Contents.LoadFromFile(Full_File_Name_And_Path);
First_Line_Of_File := Resource_File_Contents.Strings[0];
if (Copy(First_Line_Of_File, 1, 21) <> '#define CONST_VERSION') then
begin
ShowMessage ('First line of Version Info must start with "#define CONST_VERSION".' +
#13 + 'Version not incremented.');
Exit;
end;
Position_First_Dot := Pos('.', First_Line_Of_File);
if (Position_First_Dot = 0) then
begin
ShowMessage ('Version must have format "a.b.c.d".' + #13 +
'Build Number not incremented.');
Exit;
end;
Position_Second_Dot := PosEx('.', First_Line_Of_File,
Position_First_Dot+1);
if (Position_Second_Dot = 0) then
begin
ShowMessage ('Version must have format "a.b.c.d".' + #13 +
'Build Number not incremented.');
Exit;
end;
Position_Third_Dot := PosEx('.', First_Line_Of_File,
Position_Second_Dot+1);
if (Position_Third_Dot = 0) then
begin
ShowMessage ('Version must have format "a.b.c.d".' + #13 +
'Build Number not incremented.');
Exit;
end;
Position_Trailing_Backslash := PosEx('\', First_Line_Of_File,
Position_Third_Dot+1);
if (Position_Trailing_Backslash = 0) then
begin
ShowMessage ('Version must have format "a.b.c.d\000".' + #13 +
'Build Number not incremented.');
Exit;
end;
Start_of_Build_Number := Position_Third_Dot + 1;
Length_of_Build_Number := Position_Trailing_Backslash -
Start_of_Build_Number;
if (Length_of_Build_Number < 1) then
begin
ShowMessage ('Build Number must be present.' + #13 +
'Build Number not incremented.');
Exit;
end;
Build_Number_In_ASCII := Copy (First_Line_Of_File,
Start_of_Build_Number,
Length_of_Build_Number);
Success := TryStrToInt (Build_Number_In_ASCII, Build_Number_Numeric);
if (not Success) then
begin
ShowMessage ('Build Number must be numeric integer.' + #13 +
'Build Number not incremented.');
Exit;
end;
Build_Number_Numeric := Build_Number_Numeric + 1;
Build_Number_In_ASCII := IntToStr(Build_Number_Numeric);
Resource_File_Contents.Strings[0] := Copy(First_Line_Of_File, 1,
Position_Third_Dot) +
Build_Number_In_ASCII +
'\000"';
Old_Resource_File_Name := Full_File_Name_And_Path;
Old_Resource_File_Name := TPath.ChangeExtension(Old_Resource_File_Name, '~rc');
if TFile.Exists(Old_Resource_File_Name, False) then
TFile.Delete(Old_Resource_File_Name);
Success := RenameFile(Full_File_Name_And_Path, Old_Resource_File_Name);
if (not Success) then
begin
ShowMessage ('Error renaming old resource file to have extension "~rc".' + #13 +
'Build Number not incremented.');
Exit;
end;
Resource_File_Contents.SaveToFile(Full_File_Name_And_Path);
finally
Resource_File_Contents.Free;
end;
end;
procedure TIncrementBuildNumber.FormActivate (Sender: TObject);
begin
Close;
end;
end.
C) 在应增加内部版本号的项目的项目选项中:
"" "<.rc>"
D) 添加到项目源代码中,就在“program”关键字的正下方:
{$R '<whatever you called it>.res' '<whatever you called it>.rc'} // I think both names must
在这里是一样的:IIRC,当它们不同时会出错。
E) 编译、运行并享受 Auto-Increment 内部版本号的返回,尽管 Embarcadero 已移除该设施。
Jim 的内容结束
您可以使用预构建事件来更新 ProductName 或 FileDescription 值,或任何其他必须不同于基本脚本的值。