Solved

Get File version info.

Posted on 2006-07-12
6
387 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
This is a video that shows how the OnPage alerts system integrates into ConnectWise, how a trigger is set, how a page is sent via the trigger, and how the SENT, DELIVERED, READ & REPLIED receipts get entered into the internal tab of the ConnectWise …
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

930 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now