gpt4 book ai didi

delphi - 如何在一个地方为多个应用程序定义应用程序版本?

转载 作者:行者123 更新时间:2023-12-03 14:34:44 25 4
gpt4 key购买 nike

我们有一个由众多应用程序组成的系统。所有应用程序的版本都同时更改。目前,当我们发布新版本时,我们必须手动打开每个应用程序的项目选项,并逐个更改版本。有没有办法在同一版本上编译所有应用程序,例如,将其保存在全局文件中,并在编译时读取该文件并将该版本分配给项目?我只是想消除太多步骤,因为我们计划更频繁地更改版本号。我只想在一个地方改变它。这可以做到吗?以及如何?

最佳答案

您可以在纯文本文件中创建 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}

我建议将通用版本信息资源放入版本控制系统中的外部引用中,然后您可以将其 check out 到每个项目的文件夹中并轻松更新。

执行“项目”->“构建”,您的版本信息将嵌入到 .exe 中。您可以通过使用 Windows 资源管理器并查看应用程序的属性来进行验证。

CodeNewsFast 文件中的 Embarcadero Delphi 论坛中有几篇帖子(一篇是我写的,一篇是 Jim Fleming 的回复)。我的是[这里],我在其中逐步描述了如何在项目中使用预构建事件来更新我上面发布的资源脚本中的版本号。

吉姆发布了一些回复,但大约有十几篇帖子下面有一个可执行文件的源代码,可以从适合他的预构建事件中调用。 (有些事情我会做不同的事情,比如让 IDE 在命令行上传递项目名称和位置;分步文章中描述了如何执行此操作。我还会处理版本解析和以不同的方式递增,但基本应用程序是一个很好的起点。)

Embarcadero 的群组目前已关闭,但我能够从 CodeNewsFast 检索 Jim 的代码也可以在这里重现:

Ken,

Thanks to you, I got it to work.

Just in case anyone else wants to implement this solution, Below you will find the necessary steps and auxiliary program.

Jim Fleming

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) 在构建号应增加的项目的“项目选项”中:

  • 删除勾选“包含版本信息”。

  • 添加一个预构建事件,其中包含以下文本(如所写),包括两对双引号,替换 < > 中的部分:

"<自增程序exe的完整文件名和路径>""<.rc资源文件的完整文件名和路径>"

D) 添加到项目源代码,位于“program”关键字的正下方:

{$R '<whatever you called it>.res' '<whatever you called it>.rc'} // I think both names must

这里是相同的:IIRC,当它们不同时会出错。

E) 编译、运行并享受自动增量内部版本号的返回,尽管 Embarcadero 已删除该功能。

End of Jim's content

例如,您可以使用预构建事件来更新 ProductNameFileDescription 值,或任何其他必须与基本脚本不同的值。

关于delphi - 如何在一个地方为多个应用程序定义应用程序版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11782328/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com