Soon Santos
Soon Santos

Reputation: 2239

Delphi executable version returns always the same value

I am trying to get the version of my running executable so I know when my application has changed to a new version with new features.

I am using the following code to get the version:

function GetVersaoExe: string;
type
   PFFI = ^vs_FixedFileInfo;
var
   F : PFFI;
   Handle : Dword;
   Len : Longint;
   Data : Pchar;
   Buffer : Pointer;
   Tamanho : Dword;
   Parquivo: Pchar;
   Arquivo : string;
begin
   Arquivo := Application.ExeName;
   Parquivo := StrAlloc(Length(Arquivo) + 1);
   StrPcopy(Parquivo, Arquivo);
   Len := GetFileVersionInfoSize(Parquivo, Handle);
   ShowMessage(IntToStr(Len));
   Result := '';
   if Len > 0 then
   begin
      Data:=StrAlloc(Len+1);
      if GetFileVersionInfo(Parquivo,Handle,Len,Data) then
      begin
         VerQueryValue(Data, '\',Buffer,Tamanho);
         F := PFFI(Buffer);
         Result := Format('%d.%d.%d.%d',
         [HiWord(F^.dwFileVersionMs),
         LoWord(F^.dwFileVersionMs),
         HiWord(F^.dwFileVersionLs),
         Loword(F^.dwFileVersionLs)]
         );
      end;
      StrDispose(Data);
   end;
   StrDispose(Parquivo);
end;

This returns me the number 4.0.1.1.

The problem is that I've been using this function for a while and it never changes this number, it is always 4.0.1.1, I need a number that will change each time I rebuild the application to know that something has changed since the last build.

I checked about three other ways to get the version number and they all happen to do the same thing.

There is a similiar question on StackOverFlow but I still don't know if it works. I checked this question and tried to use their way but there is another problem. When I import ToolsAPI in my uses unit to use IOTAProjectOptionsConfigurations and gives me the following error: Cannot compile unit ToolsAPI.

At last I tried to solve this last problem but I couldn't.

Upvotes: 0

Views: 288

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 598021

Simply configure your project to auto-increment the version number on each new build. The Version Info page in the Project Options has a checkbox for that purpose.


That said, in the code you showed, you don't need to use StrAlloc()/StrDispose() at all. Simply pass PChar(Arquivo) as input to GetFileVersionInfoSize() and GetFileVersionInfo(), and change Data to an array of Byte (or TBytes if your version of Delphi has it) using SetLength() to allocate it and letting the compiler deallocate it automatically.

function GetVersao(const Arquivo: String): string;
type
  PFFI = ^vs_FixedFileInfo;
var
  F : PFFI;
  Handle : Dword;
  Len : Longint;
  Data : array of Byte; // or TBytes
  Buffer : Pointer;
  Tamanho : Dword;
begin
  Result := '';
  Len := GetFileVersionInfoSize(PChar(Arquivo), Handle);
  ShowMessage(IntToStr(Len));
  if Len > 0 then
  begin
    SetLength(Data, Len);
    if GetFileVersionInfo(PChar(Arquivo), Handle, Len, PByte(Data)) then
    begin
      if VerQueryValue(PByte(Data), '\', Buffer, Tamanho) then
      begin
        F := PFFI(Buffer);
        Result := Format('%d.%d.%d.%d',
          [HiWord(F^.dwFileVersionMs),
          LoWord(F^.dwFileVersionMs),
          HiWord(F^.dwFileVersionLs),
          Loword(F^.dwFileVersionLs)]
        );
      end;
    end;
  end;
end;

function GetVersaoExe: string;
begin
  Result := GetVersao(Application.ExeName);
end;

If you really want to be slick, you don't even need to use GetFileVersionInfo/Size() at all. You can use (Find|Load|Lock)Resource() to access the calling process's RT_VERSION resource directly instead:

function GetVersao(Module: THandle): string;
type
  PFFI = ^vs_FixedFileInfo;
var
  F : PFFI;
  Len : Longint;
  Data : array of Byte; // or TBytes
  Buffer : Pointer;
  Tamanho : Dword;
  hRes, hResData: THandle;
begin
  Result := '';
  hRes := FindResource(Module, MAKEINTRESOURCE(1), RT_VERSION);
  Len := SizeOfResource(hRes);
  ShowMessage(IntToStr(Len));
  if Len > 0 then
  begin
    hResData := LoadResource(Module, hRes);
    Buffer := LockResource(hResData);
    SetLength(Data, Len);
    Move(Buffer^, Data[0], Len);
    if VerQueryValue(PByte(Data), '\', Buffer, Tamanho) then
    begin
      F := PFFI(Buffer);
      Result := Format('%d.%d.%d.%d',
        [HiWord(F^.dwFileVersionMs),
        LoWord(F^.dwFileVersionMs),
        HiWord(F^.dwFileVersionLs),
        Loword(F^.dwFileVersionLs)]
      );
    end;
  end;
end;

function GetVersaoExe: string;
begin
  Result := GetVersao(GetModuleHandle(nil));
end;

Upvotes: 5

Related Questions