Reputation: 2239
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
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