Solved

Get File version info.

Posted on 2006-07-12
6
393 Views
Last Modified: 2010-04-05
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
Comment
Question by:CodedK
6 Comments
 
LVL 3

Expert Comment

by:jpedef
ID: 17090054
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
 
LVL 16

Author Comment

by:CodedK
ID: 17090244
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
 
LVL 4

Expert Comment

by:kenpem
ID: 17090497
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
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

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.

 
LVL 26

Accepted Solution

by:
Russell Libby earned 250 total points
ID: 17090534
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
 
LVL 16

Author Comment

by:CodedK
ID: 17090594
Thanks Russell :)
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17090625
No problem

Russell
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question