[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 432
  • Last Modified:

Get File version info.

Hi.

I need a small working code to retrieve some version information for a file.
I've searched EE database and saw some answers but the code is big and some times doesnt work.

Thanks in advance :)
0
CodedK
Asked:
CodedK
1 Solution
 
jpedefCommented:
This piece of code should work

const
  InfoNum = 10;
  InfoStr: array[1..InfoNum] of string = ('CompanyName',
  'FileDescription', 'FileVersion', 'InternalName', 'LegalCopyright',
  'LegalTradeMarks', 'OriginalFileName', 'ProductName', 'ProductVersion', 'Comments');

function GetFileVersionString(AFileName: string): string;
var
  VerStr: string;
  n, Len: DWORD;
  Buf: PChar;
  Value: PChar;
begin
  n := GetFileVersionInfoSize(PChar(AFileName), n);
  if n > 0 then
  begin
    Buf := AllocMem(n);
    try
      GetFileVersionInfo(PChar(AFileName), 0, n, Buf);
      if VerQueryValue(Buf, PChar('\StringFileInfo\040B04E4\FileVersion'), Pointer(Value), Len) then
        VerStr := 'Version: ' + Value
      else
        VerStr := 'Unknown version ';
    finally
      FreeMem(Buf);
    end;
  end
  else
    VerStr := 'No version information available';
  Result := VerStr;
end;
0
 
CodedKAuthor Commented:
Hi jpedef, thanks.

There is a problem with the code...
It shows 'no version info available' for files that have a version string.

I use it like this :
GetFileVersionString(Path of exe + exefilename)

How can i get the other strings like "comments","FileDescription","Company" etc ?
0
 
kenpemCommented:
Try this one:
function getVersion : string;                         // poached from the online documentation
const    NOVIDATA = '';
var
  dwInfoSize,           // Size of VERSIONINFO structure
  dwVerSize,            // Size of Version Info Data
  dwWnd: DWORD;         // Handle for the size call.
  FI: PVSFixedFileInfo; // Delphi structure; see WINDOWS.PAS
  ptrVerBuf: Pointer;   // pointer to a version buffer
  strFileName,          // Name of the file to check
  strVersion : string;  // Holds parsed version number
begin
   strFileName := paramStr( 0 );
   dwInfoSize := getFileVersionInfoSize( pChar( strFileName ), dwWnd);
   if ( dwInfoSize = 0 ) then
      result := NOVIDATA
   else
     begin
       getMem( ptrVerBuf, dwInfoSize );
       try
         if getFileVersionInfo(pChar(strFileName),dwWnd,dwInfoSize,ptrVerBuf) and verQueryValue(ptrVerBuf,'\',pointer(FI),dwVerSize) then
           strVersion := format('%d.%d.%d.%d',[hiWord(FI.dwFileVersionMS),loWord(FI.dwFileVersionMS),
                       hiWord(FI.dwFileVersionLS),loWord(FI.dwFileVersionLS)]);
       finally
         freeMem( ptrVerBuf );
       end;
     end;
  Result := strVersion;
end;
0
[Webinar] Improve your customer journey

A positive customer journey is important in attracting and retaining business. To improve this experience, you can use Google Maps APIs to increase checkout conversions, boost user engagement, and optimize order fulfillment. Learn how in this webinar presented by Dito.

 
Russell LibbySoftware Engineer, Advisory Commented:
The problem is that the code does not take into account the language translation tables that the file was built with, eg on my system I would need to use:

\StringFileInfo\040904B0\{value}

The following code (modified from above) makes use of the lang translation tables to return the desired values.

Russell

---


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation
{$R *.DFM}

const
  InfoNum           = 10;
  InfoStr:          Array [1..InfoNum] of String =
                    (
                       'CompanyName',
                       'FileDescription',
                       'FileVersion',
                       'InternalName',
                       'LegalCopyright',
                       'LegalTradeMarks',
                       'OriginalFileName',
                       'ProductName',
                       'ProductVersion',
                       'Comments'
                    );

type
  TLangCharset      =  Array [0..1] of Word;
  PLangCharsets     =  ^TLangCharsets;
  TLangCharsets     =  Array [0..MaxWord] of TLangCharset;

function GetFileInfoString(FileName: String; Info: Integer): String;
var  dwSize:        DWORD;
     dwLength:      DWORD;
     dwIndex:       Integer;
     lpszBuffer:    PChar;
     lpCharset:     PLangCharsets;
     lpValue:       Pointer;
     wTemp:         Word;
begin

  // Clear result
  SetLength(result, 0);

  // Get file version info size
  dwSize:=GetFileVersionInfoSize(PChar(FileName), dwLength);

  // Check result
  if (dwSize > 0) then
  begin
     // Allocate memory
     lpszBuffer:=AllocMem(dwSize);
     try
        // Get file version info
        if GetFileVersionInfo(PChar(FileName), 0, dwSize, lpszBuffer) then
        begin
           // Query for the translation table so we know what lang-charset is being used
           if VerQueryValue(lpszBuffer, '\VarFileInfo\Translation', lpValue, dwLength) and (dwLength >= SizeOf(TLangCharset)) then
           begin
              // Get the language charset array
              lpCharset:=lpValue;
              // Calculate the number of items in the array
              dwSize:=dwLength div SizeOf(TLangCharset);
              // Walk the charsets
              for dwIndex:=0 to Pred(dwSize) do
              begin
                 // Get the desired info string
                 if VerQueryValue(lpszBuffer, PChar('\StringFileInfo\'+IntToHex(lpCharset^[dwIndex][0], 4)+
                                  IntToHex(lpCharset^[dwIndex][1], 4)+'\'+InfoStr[Info]), lpValue, dwLength) then
                 begin
                    // Set result string
                    SetString(result, PChar(lpValue), dwLength);
                    // Done processing
                    break;
                 end;
              end;
           end;
        end;
     finally
        // Free allocated memory
        FreeMem(lpszBuffer);
     end;
  end;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin

  // CompanyName
  ShowMessage(GetFileInfoString('c:\windows\system32\calc.exe', 1));
  // FileDescription
  ShowMessage(GetFileInfoString('c:\windows\system32\calc.exe', 2));
  // FileVersion
  ShowMessage(GetFileInfoString('c:\windows\system32\calc.exe', 3));
  // InternalName
  ShowMessage(GetFileInfoString('c:\windows\system32\calc.exe', 4));

end;

end.

0
 
CodedKAuthor Commented:
Thanks Russell :)
0
 
Russell LibbySoftware Engineer, Advisory Commented:
No problem

Russell
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now