- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们有一个由众多应用程序组成的系统。所有应用程序的版本都同时更改。目前,当我们发布新版本时,我们必须手动打开每个应用程序的项目选项,并逐个更改版本。有没有办法在同一版本上编译所有应用程序,例如,将其保存在全局文件中,并在编译时读取该文件并将该版本分配给项目?我只是想消除太多步骤,因为我们计划更频繁地更改版本号。我只想在一个地方改变它。这可以做到吗?以及如何?
最佳答案
您可以在纯文本文件中创建 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
例如,您可以使用预构建事件来更新 ProductName
或 FileDescription
值,或任何其他必须与基本脚本不同的值。
关于delphi - 如何在一个地方为多个应用程序定义应用程序版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11782328/
在complier.h中有一个宏定义如下: # define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) 但是这里我有一个问题,就是哪里
curl_easy_setopt 的选项在哪里?定义?我试图寻找 CURLOPT_VERBOSE 和其他一些整数值,但这些似乎没有在 curl.h 中明确定义。 最佳答案 第 792 行: #ifde
我确实有一个如下所示的类(class): //.h file class __declspec(dllimport) MyClass { public: //stuff pri
作者: zhuwenzhuang, 2024.05.08. 阅读前假设读者熟悉数据库使用,了解 SQL 的语法和关系算子的大概含义, 能通过 EXPLAIN 命令查看数据库执行计划. 0 前言
我似乎无法找到是否可以声明一个 header 对象以便在响应 header 中重用它,有一些示例定义了响应模式的对象,但它不会转置为响应 header 。我只设法制作了一个可重用的响应对象,如下所示:
css 选择器 * + * 实际上是什么意思?当您执行检查元素时,您可以在谷歌浏览器的控制台中看到它。在我看来,这似乎是对 "Every second child"应用一种风格,但仍然想确定。谁能帮我
我试图弄清楚基本的IO Haskell 函数是定义好的,所以我使用了this reference我到了putChar函数定义: putChar :: Char -> IO () putChar
我得到了一个自动生成的文件,该文件定义了程序集属性,我正在尝试理解内容。 [assembly: global::System.Runtime.Versioning.TargetFrameworkAtt
This文档演示了如何检查变量是否先前已在 gnuplot 脚本中定义。 文档中的示例: a = 10 if (exists("a")) print "a is defined" if (!exist
好吧,这是一个相当基本的问题:我正在关注 SICP 视频,我对 define、let 和 之间的区别有点困惑设置!. 1) 根据 Sussman 在视频中的说法,define 只允许为变量附加一个值一
我一直在尝试定义一个包含只能具有以下三个值之一的字段的 XSD: 绿色 红色 蓝色 本质上,我想在架构级别定义严格的枚举。 我的第一次尝试似乎是错误的,我不确定修复它的“正确”方法。
有人可以定义“POCO”到底是什么意思吗?我越来越频繁地遇到这个术语,我想知道它是否仅与普通类有关还是意味着更多? 最佳答案 “普通旧式 C# 对象” 只是一个普通的类,没有描述基础结构问题或域对象不
在我经常看到的一些django模型中 myfield = models.CharField(_('myfield')) class_name = models.CharField(_('Type'),
每当 BOOL 数据类型不容易预定义时,我都会使用以下定义进行 boolean 运算, typedef unsigned char BOOL; (由于内存使用)。 我意识到出于性能原因,使用本地总线宽
l_ABC_BEANVector = utilRemote.fnGetVector("ABC_COVBEANVector"); 编码的含义是什么?任何帮助,我真的很感激。谢谢 最佳答案 唯一可以肯定地
我正在使用 javacc 开发一个项目,我遇到问题并需要一些帮助,我的文件中有这样的内容: STRING COPYRIGHT (C) 2003, 2004 SYNOPSYS, INC.; 我为单词 S
我想弄清楚基本的 IO定义了 Haskell 函数,所以我使用了 this reference然后我到了 putChar函数定义: putChar :: Char -> IO () putCha
我在具体类中使用 @property 定义 getter 时遇到问题。这是Python代码: from abc import ABCMeta, abstractproperty class abstr
我正在为大学用 C 语言编写一个小游戏,但我陷入了困境。我(在头文件中)有这个结构: typedef struct{ game_element field[MAX_ROWS][MAX_COLU
我一直在 .l 文件中创建标记定义。由于数据集数量庞大,它变得有点乏味。有没有办法读取文件中的所有单词,例如包含所有名词的 noun.txt 并给所有名词一个标记。 基本上,我想自动化这部分: %%
我是一名优秀的程序员,十分优秀!