Jak zdefiniować wersję aplikacji w jednym miejscu dla wielu aplikacji?

Mamy system, który składa się z wielu aplikacji. Wszystkie aplikacje mają zmienioną wersję w tym samym czasie. Obecnie, kiedy wydajemy nową wersję, musimy ręcznie otworzyć Opcje projektu każdej aplikacji i zmienić wersję jeden po drugim. Czy jest jakiś sposób kompilacji wszystkich aplikacji na tej samej wersji, na przykład, zapisać go w pliku globalnym i po kompilacji, przeczytać ten plik i przypisać tę wersję do projektu? Staram się tylko wyeliminować zbyt wiele kroków, ponieważ planujemy częściej zmieniać numery wersji. Chciałbym to zmienić tylko w jednym miejscu. Czy można to zrobić? i jak?

Author: TLama, 2012-08-02

3 answers

Możesz utworzyć VERSIONINFO zasób, w zwykłym pliku tekstowym (np., 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
}
}

Uwaga: terminatory null w stylu C (\0) są potrzebne na końcu każdego elementu, jak pokazano, aby kompilator zasobów mógł poprawnie zakończyć ciągi znaków. W przeciwnym razie, gdy używasz Eksploratora do wyświetlania informacji o wersji pliku wykonywalnego, możesz uzyskać zniekształcone lub częściowo skonkatenowane wartości.

Dodaj wiersz do pliku źródłowego projektu:

{$R VersionInfo.res VersionInfo.rc}

Proponuję umieścić wspólny źródło informacji o wersji do odniesienia zewnętrznego w systemie kontroli wersji, a następnie możesz po prostu sprawdzić go w folderze każdego projektu i łatwo go zaktualizować.

Wykonaj projekt - > Build, A informacja o wersji zostanie osadzona w .exe. Możesz sprawdzić, używając Eksploratora Windows i przeglądając właściwości aplikacji.

Jest kilka postów (jeden przeze mnie i jeden w odpowiedzi Jima Fleminga) na forach Embarcadero Delphi w archiwum CodeNewsFast. Mój jest [tutaj], gdzie, Opisuję krok po kroku, jak użyć zdarzenia pre-build w projekcie, aby zaktualizować numer wersji w skrypcie zasobów, który napisałem powyżej.

Jim napisał kilka odpowiedzi, ale około kilkunastu postów znajduje się źródło pliku wykonywalnego, który można wywołać ze zdarzenia pre-build, które działa dla niego. (Są pewne rzeczy, które zrobiłbym inaczej, jak pozwolenie IDE przekazać nazwę projektu i lokalizację w wierszu poleceń; jak to zrobić jest opisane w artykule krok po kroku. Też bym sobie poradził wersja parsuje i inkrementuje inaczej, ale podstawowa aplikacja jest dobrą lokalizacją początkową.)

Grupa Embarcadero jest obecnie nieaktywna, ale udało mi się pobrać kod Jima z CodeNewsFast i odtworzyć go tutaj:

Ken,

Dzięki tobie udało mi się.

Na wszelki wypadek, gdyby ktoś jeszcze chciał wdrożyć to rozwiązanie, Poniżej znajdziesz niezbędne kroki i program pomocniczy.

Jim Fleming

A) Utwórz plik informacji o wersji w katalogu projektu lub gdziekolwiek indziej, za pomocą następującego

Zawartość i rozszerzenie pliku .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) Utwórz nowy projekt w jakimś folderze, Kod tylko modułu powinien być podobny do:

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) w opcjach projektu, którego numer budowy powinien być zwiększany:

  • Usuń zaznaczenie "Dołącz informacje o wersji".

  • Dodaj zdarzenie pre-build z po tekście, jak napisano, w tym dwie pary podwójnych cudzysłowów, zastępując części wewnątrz :

" " " "

D) dodać do źródła projektu, tuż pod słowem kluczowym "program":

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

Być tym samym tutaj: IIRC, dostał błędy, gdy były różne.

E) kompilować, uruchamiać i cieszyć się powrotem Auto-Increment budować numery, pomimo Embarcadero usunął obiekt.

Koniec treści Jima

Można użyć zdarzenia pre-build, aby na przykład zaktualizować wartości ProductName lub FileDescription, lub inne, które muszą być inne niż skrypt podstawowy.

 24
Author: Ken White,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-21 04:50:58

UPDATE: nie jest częścią samego RADStudio, ale pochodzi z Ddevextensions Andreasa Hausladena (które już kiedyś miałem...!).

Możesz to zrobić z poziomu IDE {[5] } z ProjectGroup pod warunkiem zainstalowania doskonałego DDevExtensions od Andreasa Hausladena.

  • mieć grupę projektową, która zawiera wszystkie twoje projekty
  • upewnij się, że każdy z twoich projektów ma " Include version information in project" sprawdzone w Options|Version Info page.
  • użyj menu Project|Set Versioninfo..., aby otworzyć okno dialogowe Set Project Versioninfo (tylko raz, bieżący projekt nie ma znaczenia).
  • tam możesz określić wszystkie informacje o wersji i wybrać, który "Zastosuj do wszystkich" lub tylko do wybranych projektów, jeśli zaznaczyłeś "Zastosuj do wybranych".

Na przykład, zobacz jak ustawić wersję do obu projektów naraz: Przykład gdzie ustawiam wersję do obu projektów naraz

Następnie Build All Na ProjectGroup wyprodukował oba EXY z wersją ustawioną na 1.1.1.9 i wszystkie inne szczegóły...

 14
Author: François,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-02 23:28:50

Jest to jeden z przypadków użycia dzPrepBuild: http://www.dummzeuch.de/delphi/dzprepbuild/englisch.html

(uwaga: projekt został przeniesiony do sourceforge, ponieważ berlios miał zostać zamknięty w zeszłym roku. http://sourceforge.net/projects/dzprepbuild/)

 2
Author: dummzeuch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-03 12:48:35