2

I'm loading package at runtime via LoadPackage(). Let's say after load I want to check the version of the package to ensure it's the newest. How can I do that?

JustMe
  • 2,329
  • 3
  • 23
  • 43

1 Answers1

7

A package is just a special type of dll, So you can use the GetFileVersion function defined in the SysUtils unit, this function returns the most significant 32 bits of the version number. so does not include the release and/or build numbers.

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

 Var
   FileVersion : Cardinal;
begin
  try
    FileVersion:=GetFileVersion('C:\Bar\Foo.bpl');
    Writeln(Format('%d.%d',[FileVersion shr 16, FileVersion and $FFFF]));
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

If you want retrieve the full version number (with release and build numbers included) you can use the GetFileVersionInfoSize, VerQueryValue and GetFileVersionInfo WinApi functions.

function GetFileVersionStr(const AFileName: string): string;
var
  FileName: string;
  LinfoSize: DWORD;
  lpdwHandle: DWORD;
  lpData: Pointer;
  lplpBuffer: PVSFixedFileInfo;
  puLen: DWORD;
begin
  Result := '';
  FileName := AFileName;
  UniqueString(FileName);
  LinfoSize := GetFileVersionInfoSize(PChar(FileName), lpdwHandle);
  if LinfoSize <> 0 then
  begin
    GetMem(lpData, LinfoSize);
    try
      if GetFileVersionInfo(PChar(FileName), lpdwHandle, LinfoSize, lpData) then
        if VerQueryValue(lpData, '\', Pointer(lplpBuffer), puLen) then
          Result := Format('%d.%d.%d.%d', [
            HiWord(lplpBuffer.dwFileVersionMS),
            LoWord(lplpBuffer.dwFileVersionMS),
            HiWord(lplpBuffer.dwFileVersionLS),
            LoWord(lplpBuffer.dwFileVersionLS)]);
    finally
      FreeMem(lpData);
    end;
  end;

end;
RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • Thanks for clarifying how to translate FileVersion to more readable form :-) – JustMe Oct 22 '12 at 20:08
  • 5
    Since the file is already loaded in memory, it is actually more efficient and more accurate to access its `RT_RESOURCE` resource directly, such as with `TResourceStream`, instead of using `GetFileVersionInfo()`, at least as far as the version number is concerned since it is static data. – Remy Lebeau Oct 22 '12 at 21:44
  • @RemyLebeau Could you point me to documentation. I cannot find it. – JustMe Oct 23 '12 at 07:34
  • Microsoft doesn't want you to access the `RT_VERSION` resource directly, mainly because `GetFileVersionInfo()` does some dynamic data hookups that `VerQueryValue()` looks for. So Microsoft does not really document how to access the resource directly. But if the .exe file is inaccessible or modified, `GetFileVersionInfo()` can return bad data, so it may be desirable to access the resource directly since it is already in memory... – Remy Lebeau Oct 23 '12 at 22:58
  • ... it is safe to [access the resource data directly](http://stackoverflow.com/questions/1717844/how-to-determine-delphi-application-version), as long as you account for one caveat - you have to dynamically allocate a memory block and copy the resource data into it before passing it to `VerQueryValue()`, otherwise it will crash with a memory access error. – Remy Lebeau Oct 23 '12 at 22:59