如何在一个地方为多个应用程序定义应用程序版本? [英] How to define application version in one place for multiple applications?

查看:212
本文介绍了如何在一个地方为多个应用程序定义应用程序版本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

您可以创建一个 VERSIONINFO 资源纯文本文件(例如 Versioninfo.rc

  1 VERSIONINFO 
FILEVERSION 2,0,0,0
PRODUCTVERSION 2,0,0,0
FILEOS 0x4
FILETYPE 0x1
{
BLOCKStringFileInfo
{
BLOCK040904E4
{
VALUECompanyName,您的公司名称Here\0
VALUEFileDescription,您的文件描述Here\\ \\ 0
VALUEFileVersion,2.0.0.0\0
VALUEInternalName,您的内部名称\0
VALUELegalCopyright Notice\0
VALUELegalTrademarks,您的商标声明\0
VALUEOriginalFilename,YourExeName\0
VALUEProductName,您的产品名称\0
VALUEProductVersion,2.0.0.0\0
VALUEComments,No Comments\0
}
}

BLOCKVarFileInfo
{
VALUETranslation,0x0409 0x04E4
}
}

注意:在每个项目的结尾处需要C样式空终止符( \0 ),如图所示以便资源编译器正确地终止字符串。否则,当您使用Explorer来显示可执行文件的版本信息时,可能会出现乱码或部分拼接的值。



向项目源文件添加一行:

  {$ R VersionInfo.res VersionInfo.rc} 

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



执行Project - > Build,您的版本信息嵌入在.exe中。您可以使用Windows资源管理器并查看您的应用程序的属性进行验证。



有几个帖子(一个由我和一个在Jim Fleming的回复中)在Embarcadero Delphi论坛在CodeNewsFast存档。 Mine是[这里],其中,我逐步描述如何使用预建置事件在您的项目中更新我上面发布的资源脚本中的版本号。



Jim发布了几个回复,但大约有十几个帖子等等,有一个可执行文件的源代码,可以从为他工作的预构建事件调用。 (有一些事情我会做不同的,比如让IDE在命令行上传递项目名称和位置;如何做到这一点在一步一步的文章中描述我还将处理版本解析和但是基本的应用程序是一个很好的开始位置。)



Embarcadero的组目前已经关闭,但我可以从 CodeNewsFast ,并且可以在此重现:


Ken,



感谢你,我得以工作。





Jim Fleming


A)在您的项目目录或任何位置创建您的版本信息资源文件,其中包含以下



内容和文件扩展名.rc :

  //注意\000!在这里和其他地方!!!! 
// C字符串终止符!
#define CONST_VERSION4.1.1.1003\000

1 VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEOS 0x4
FILETYPE 0x1
{
BLOCKStringFileInfo
{

BLOCK040904E4//如果您的语言是不是英语和字符集不是

1252(多语言)。
{
VALUECompanyName,Whatever\000
VALUEFileDescription,Whatever\000
VALUEFileVersion,CONST_VERSION
VALUE InternalName,My Internal Name\000
VALUELegalCopyright,版权所有©whoever\000
VALUELegalTrademarks,\000
VALUE OriginalFileName,如果您希望\000
VALUEProductName,What much you\000
VALUEProductVersion,CONST_VERSION
VALUEComments希望添加\000
}
}
BLOCKVarFileInfo
{
VALUETranslation,0x0409 0x04E4
}
}

B)在某个文件夹中创建一个新项目,模块的代码应该类似于: / p>

 单位FormIncrementBuildNumber; 

接口

使用
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
{私人声明}
public
{公共声明}
end;

var
IncrementBuildNumber:TIncrementBuildNumber;

实现

{$ R * .dfm}

程序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;
成功:Boolean;
begin
if(System.ParamCount<> 1)then
begin
ShowMessage('Resource File name not in first command-line parameter。');
退出;
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。
退出;
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 +'版本未递增。
退出;
end;

Position_First_Dot:= Pos('。',First_Line_Of_File);
if(Position_First_Dot = 0)then
begin
ShowMessage('Version must have formata.b.c.d。'+#13 +
'Build Number not incremented'。
退出;
end;

Position_Second_Dot:= PosEx('。',First_Line_Of_File,
Position_First_Dot + 1);
if(Position_Second_Dot = 0)then
begin
ShowMessage('Version must have formata.b.c.d。'+#13 +
'Build Number not incremented'。
退出;
end;

Position_Third_Dot:= PosEx('。',First_Line_Of_File,
Position_Second_Dot + 1);

if(Position_Third_Dot = 0)then
begin
ShowMessage('Version必须有格式为abcd。'+#13 +
'Build Number不增加。 ');

退出;
end;

Position_Trailing_Backslash:= PosEx('\',First_Line_Of_File,
Position_Third_Dot + 1);

if(Position_Trailing_Backslash = 0)then
begin
ShowMessage('Version必须有格式abcd\000。'+#13 +
'不增加。
退出;
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);
成功:= 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'。
退出;
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');

如果TFile.Exists(Old_Resource_File_Name,False)then
TFile.Delete(Old_Resource_File_Name); $成功:= RenameFile(Full_File_Name_And_Path,Old_Resource_File_Name);
if(not Success)then
begin
ShowMessage('错误重命名旧资源文件有扩展名〜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
关闭;
end;

end。

C)在其项目编号应递增的项目的项目选项中:




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


  • 构建事件与下面的文本,如写,包括两对双引号, >:






添加到项目源,在program关键字下面:

  {$ R'<我想这两个名字都必须

在这里:IIRC,当它们不同时出现错误。



E)编译,运行并享受自动增量构建号的返回,尽管Embarcadero已删除






Jim的内容结束


您可以使用pre-build事件来更新 ProductName FileDescription 值,或任何其他必须与基本脚本不同。


We have a system which consists of numerous applications. All applications have their version changed at the same time. Currently, when we release a new version, we have to manually open the project options of each application and change the version one by one. Is there any way to compile all applications on the same version, for example, save it in a global file and upon compilation, read this file and assign that version to the project? I'm just trying to eliminate too many steps, because we plan on changing the version numbers more frequently. I'd like to change it in one place only. Can this be done? and how?

解决方案

You can create a VERSIONINFO resource, in a plain text file (eg., 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
}
}

Note: The C-style null terminators (\0) are needed at the end of each item as shown in order for the resource compiler to properly terminate the strings. Otherwise, when you use Explorer to display the version information for the executable you may get garbled or partially concatenated values.

Add a line to your project source file:

{$R VersionInfo.res VersionInfo.rc}

I suggest putting the common version info resource into an externals reference in your version control system, and then you can just check it out into each project's folder and update it easily.

Do a Project->Build, and your version info is embedded in the .exe. You can verify by using Windows Explorer and viewing the properties of your app.

There's a couple of posts (one by me and one in a response by Jim Fleming) in the Embarcadero Delphi forums at CodeNewsFast archives. Mine is [here], where, I describe step-by-step how to use a pre-build event in your project to update the version number in the resource script I posted above.

Jim posts a few replies, but about a dozen posts or so down there's source for an executable that can be called from the pre-build event that works for him. (There are some things I'd do differently, like letting the IDE pass the project name and location on the command line; how to do so is described in the step-by-step article. I'd also handle the version parsing and incrementing differently, but the basic app is a good starting location.)

Embarcadero's groups are currently down, but I was able to retrieve Jim's code from CodeNewsFast as well, and can reproduce it here:

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) Create your Version Info resource file in your project directory or wherever, with the following

contents, and file extension .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) Create a new project in some folder, code of only module should be similar to:

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) In Project Options of the project whose build number should be incremented:

  • Remove the tick "include version info".

  • Add a pre-build event with the following text, as written, including the two pairs of double-quotes, substituting the parts within < >:

"" ""

D) Add to the project source, right below the "program" keyword:

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

be the same here: IIRC, got errors when they were different.

E) Compile, run and enjoy the return of Auto-Increment build numbers, despite Embarcadero's having removed the facility.

End of Jim's content

You could use the pre-build event to, for instance, update the ProductName or FileDescription values, or any others that have to be different from the base script.

这篇关于如何在一个地方为多个应用程序定义应用程序版本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆