Ответ 1
Вы можете создать ресурс 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
) необходимы в конце каждого элемента, как показано для того, чтобы компилятор ресурсов правильно завершил строки. В противном случае, когда вы используете Explorer для отображения информации о версии исполняемого файла, вы можете получить искаженные или частично объединенные значения.
Добавьте строку в исходный файл вашего проекта:
{$R VersionInfo.res VersionInfo.rc}
Я предлагаю поместить общий информационный ресурс о версии в ссылку на внешнюю версию в вашей системе управления версиями, а затем вы можете просто проверить его в каждой папке проекта и легко обновить.
Выполните Project-> Build, и информация о вашей версии будет встроена в .exe. Вы можете проверить это, используя Windows Explorer и просмотрев свойства вашего приложения.
На форумах Embarcadero Delphi в архивах CodeNewsFast есть пара постов (одно от меня и одно от Джима Флеминга). Мой [здесь], где я опишу пошагово, как использовать событие pre-build в вашем проекте для обновления номера версии в скрипте ресурса, который я выложил выше.
Джим публикует несколько ответов, но около десятка сообщений или около того источника исходного кода для исполняемого файла, который может быть вызван из события предварительной сборки, которое работает для него. (Есть некоторые вещи, которые я бы делал по-другому, например, позволяя IDE передавать имя и местоположение проекта в командной строке; как это сделать, описано в пошаговой статье. я также обработал бы разбор версии и инкрементно увеличивается, но базовое приложение является хорошей отправной точкой.)
Группы Embarcadero в настоящее время недоступны, но я смог также извлечь код Джима из CodeNewsFast и воспроизвести его здесь:
Ken,
Благодаря вам, я заставил его работать.
На случай, если кто-то еще захочет реализовать это решение, ниже вы найдете необходимые шаги и вспомогательную программу.
Джим Флеминг
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) В опциях проекта проекта, номер сборки которого должен быть увеличен:
Снимите галочку "включить информацию о версии".
Добавьте событие перед сборкой со следующим текстом, как написано, включая две пары двойных кавычек, заменяя части внутри & lt; >:
"& lt; полное имя файла и путь к программе автоинкремента exe & gt;" "& lt; полное имя файла и путь к файлу ресурса .rc & gt;"
D) Добавьте к источнику проекта, прямо под ключевым словом "программа":
{$R '<whatever you called it>.res' '<whatever you called it>.rc'} // I think both names must
здесь то же самое: IIRC получил ошибки, когда они отличались.
E) Скомпилируйте, запустите и наслаждайтесь возвращением номеров сборки с автоматическим приращением, несмотря на то, что Embarcadero удалил объект.
Конец содержимого Jim
Вы можете использовать событие предварительной сборки, например, для обновления значений ProductName
или FileDescription
или любых других, которые должны отличаться от базового сценария.