* * *

Author Topic: Exception in TFileVersionInfo.ReadFileInfo  (Read 615 times)

OLLI_S

  • New member
  • *
  • Posts: 19
Exception in TFileVersionInfo.ReadFileInfo
« on: July 11, 2018, 09:45:08 pm »
Hello,

I get some exceptions when I read the file info from some applications and the method I am using is provided by Lazarus.
I use Lazarus 1.8.4 in Windows 10 Pro German.
My programming skills I would estimate between beginner and intermediate.

I programmed a little tool that reads all information (like copyright, version info, etc) from applications.
I used the following code example: http://wiki.freepascal.org/Show_Application_Title,_Version,_and_Company

I created a new project in Lazarus, added a button and for the Button1Click event I pasted some code from the WIKI article above.
Here is the complete source of my unit:

Code: Pascal  [Select]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  9.  
  10.   fileinfo,
  11.   winpeimagereader; {need this for reading exe info}
  12.  
  13. type
  14.  
  15.   { TForm1 }
  16.  
  17.   TForm1 = class(TForm)
  18.     Button1: TButton;
  19.     procedure Button1Click(Sender: TObject);
  20.   private
  21.  
  22.   public
  23.  
  24.   end;
  25.  
  26. var
  27.   Form1: TForm1;
  28.  
  29. implementation
  30.  
  31. {$R *.lfm}
  32.  
  33. { TForm1 }
  34.  
  35. procedure TForm1.Button1Click(Sender: TObject);
  36.  
  37. var
  38.   FileVerInfo: TFileVersionInfo;
  39.  
  40. begin
  41.  
  42.   FileVerInfo := TFileVersionInfo.Create(nil);
  43.  
  44.   try
  45.  
  46.     FileVerInfo.FileName := 'C:\lazarus\lazarus.exe';
  47.     FileVerInfo.ReadFileInfo;
  48.     ShowMessage(FileVerInfo.VersionStrings.Text);
  49.  
  50.   finally
  51.     FileVerInfo.Free;
  52.   end;
  53.  
  54. end;
  55.  
  56. end.

This works perfectly for most applications.
But some applications raise exceptions at the line FileVerInfo.ReadFileInfo; (line 47).

Examples:
  • C:\Program Files\FreeCommander XE\FreeCommander.exe
    Exception Message: Cannot find resource: Type = 1, Name = 17, Lang ID = 0800)
  • C:\Program Files (x86)\System Explorer\SystemExplorer.exe
    Exception Message: Cannot find resource: Type = 1, Name = 12, Lang ID = 0000)
  • D:\PortableApps\PortableApps\FirefoxPortable\App\Firefox\firefox.exe
    Exception Message: Duplicate key '0'
  • D:\PortableApps\PortableApps\_ToDoList\ToDoList.exe
    Exception Message: Duplicate key 'oList'
As I wrote above I am not a good programmer.
But in FileVerInfo.ReadFileInfo I see no exception handling (the block "except").
Could that be the problem?
Is this a problem that can be fixed from your side (Lazarus Developers) or do I have to do anything?

I also can not set a breakpoint in FileVerInfo.ReadFileInfo to see what line causes the problems (the debugger does not stop, no matter where I set the breakpoint).
If you have any tips how I can make the breakpoint working, this would be fantastic.

I have in Lazarus the two additional packages anchordockingdsgn and sparta_DockedFormEditor.
I hope that this is not the reason for my problems (but I think not).

Thank you for your help!

Best regards

OLLI
« Last Edit: July 11, 2018, 10:17:34 pm by OLLI_S »

ASerge

  • Hero Member
  • *****
  • Posts: 827
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #1 on: July 12, 2018, 06:34:19 am »
I get some exceptions when I read the file info from some applications and the method I am using is provided by Lazarus.
Please, give a link to the "some applications" exe file (without setup), for testing.

OLLI_S

  • New member
  • *
  • Posts: 19
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #2 on: July 12, 2018, 11:04:18 am »
Hello ASerge,

Please, give a link to the "some applications" exe file (without setup), for testing.

I posted the names of some of these applications (Firefox, System Explorer, etc) in my first posting.
I suppose you have Linux because you asked for the EXE without installers?
So I will upload the EXE files to OneDrive tonight and send the links.

OLLI
« Last Edit: July 12, 2018, 12:39:18 pm by OLLI_S »

ASerge

  • Hero Member
  • *****
  • Posts: 827
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #3 on: July 12, 2018, 04:29:15 pm »
I posted the names of some of these applications (Firefox, System Explorer, etc) in my first posting.
Oops, missed FireFox.
Yeah, it looks like a bug. If you need only under Windows, here's a quick made module (attached), it seems to work.
Code: Pascal  [Select]
  1. uses VerInfo;
  2.  
  3. procedure TForm1.Button1Click(Sender: TObject);
  4. var
  5.   VerInfo: TVersionInfo;
  6.  
  7.   procedure AppendInfo(const Value: string);
  8.   begin
  9.     Memo1.Append(Value + '=' + VerInfo[Value]);
  10.   end;
  11.  
  12. var
  13.   LV: TLongVersion;
  14. begin
  15.   VerInfo := TVersionInfo.Create('c:\Program Files (x86)\Mozilla Firefox\firefox.exe');
  16.   try
  17.     Memo1.Clear;
  18.     AppendInfo(CviFileVersion);
  19.     AppendInfo(CviFileDescription);
  20.     AppendInfo(CviLegalCopyright);
  21.     AppendInfo(CviOriginalFilename);
  22.     AppendInfo(CviProductName);
  23.     AppendInfo('BuildID');
  24.     LV := VerInfo.FileLongVersion;
  25.     Memo1.Append(Format('FileLongVersion=%d.%d.%d.%d', [LV.Words[3], LV.Words[2], LV.Words[1], LV.Words[0]]));
  26.   finally
  27.     VerInfo.Free;
  28.   end;
  29. end;

OLLI_S

  • New member
  • *
  • Posts: 19
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #4 on: July 12, 2018, 05:47:33 pm »
Hello,

I copied your VerInfo.pp into the folder of my project and use it like you did in your source code.
It is working, all apps are now shown without any exceptions!
Fantastic work!

Is this a fix that will be included in Lazarus in the future?
So I don't need your code in my project folder?

Thank you again and best regards

OLLI
« Last Edit: July 12, 2018, 05:58:27 pm by OLLI_S »

ASerge

  • Hero Member
  • *****
  • Posts: 827
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #5 on: July 12, 2018, 06:02:10 pm »
Is this a fix that will be included in Lazarus in the future?
Given the cross-platform nature of the FPC, it is very doubtful. Just use it in your project.

OLLI_S

  • New member
  • *
  • Posts: 19
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #6 on: July 12, 2018, 07:47:42 pm »
Given the cross-platform nature of the FPC, it is very doubtful. Just use it in your project.

OK, but thank you for providing the code, I will use it in my project.

OLLI_S

  • New member
  • *
  • Posts: 19
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #7 on: July 15, 2018, 11:40:00 pm »
@ASerge
I added your code and it is working perfectly (I tested many apps).

But one user reported that he gets no information when he tries to read them from the application Acronis True Image Home.
I downloaded and installed this app (in a VM) and I also get no information from this app (the memo is empty, just the following lines get a result:

Code: Pascal  [Select]
  1.     LV := VerInfo.FileLongVersion;
  2.     Memo1.Append(Format('FileLongVersion=%d.%d.%d.%d', [LV.Words[3], LV.Words[2], LV.Words[1], LV.Words[0]]));
  3.  
  4.     LV := VerInfo.ProductLongVersion;
  5.     Memo1.Append(Format('FileLongVersion=%d.%d.%d.%d', [LV.Words[3], LV.Words[2], LV.Words[1], LV.Words[0]]));


A trial version of Acronis True Image Home can be downloaded here: https://www.acronis.com/en-us/personal/computer-backup/

I uploaded the EXE to my OneDrive (https://1drv.ms/f/s!AsiLVok82IpQg_97o977pmEQx4gi9A)
I have protected the folder with a password (because I fear legal issues when I upload and share an application) and send you the password via a PM.

Can you please try your code with this EXE and tell me where the problem might be?
Thank you!

Best regards

OLLI
« Last Edit: July 15, 2018, 11:45:21 pm by OLLI_S »

ASerge

  • Hero Member
  • *****
  • Posts: 827
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #8 on: July 16, 2018, 07:20:03 am »
@ASerge
But one user reported that he gets no information when he tries to read them from the application Acronis True Image Home.
Can you please try your code with this EXE and tell me where the problem might be?
Problem in Acronis True Image.
There is it's VersionInfo block:
Code: C  [Select]
  1. 1 VERSIONINFO
  2. FILEVERSION 22,5,1,12510
  3. PRODUCTVERSION 22,5,1,12510
  4. FILEOS 0x4
  5. FILETYPE 0x1
  6. {
  7. BLOCK "StringFileInfo"
  8. {
  9.         BLOCK "040904b0"
  10.         {
  11.                 VALUE "Comments", "http://www.acronis.com/"
  12.                 VALUE "CompanyName", "Acronis International GmbH"
  13.                 VALUE "FileDescription", "Acronis True Image 2018"
  14.                 VALUE "FileVersion", "22,5,1,12510"
  15.                 VALUE "InternalName", "ti_console"
  16.                 VALUE "LegalCopyright", "Copyright (C) Acronis International GmbH, 2002-2017."
  17.                 VALUE "LegalTrademarks", "Acronis International GmbH. All rights reserved."
  18.                 VALUE "OriginalFilename", "ti_console.exe"
  19.                 VALUE "ProductName", "Acronis True Image 2018"
  20.                 VALUE "ProductVersion", "22,5,1,12510"
  21.         }
  22. }
  23.  
  24. BLOCK "VarFileInfo"
  25. {
  26.         VALUE "Translation", 0x0000 0x04B0
  27. }
  28. }
As you can see VarFileInfo=0x0000 0x04B0, but StringFileInfo contains only "040904b0", and the block "000004b0" does not. This is a mistake of developers of acronis.

You can tweak the programs to account for this particular error so:
Code: Pascal  [Select]
  1. function TVersionInfo.GetVerValue(const Name: string): string;
  2. type
  3.   TTranslateInfo = packed record
  4.     LangId, CodePage: Word;
  5.   end;
  6. const
  7.   Default: TTranslateInfo = (LangId:$0409; CodePage:1252);
  8. var
  9.   PLang: ^TTranslateInfo;
  10.   PValue: PChar;
  11.   BlockName: string;
  12. begin
  13.   Result := '';
  14.   PLang := VerGetValue(FBuffer, '\VarFileInfo\Translation');
  15.   if PLang = nil then
  16.     PLang := @Default;
  17.   FmtStr(BlockName, '\StringFileInfo\%.4x%.4x\%s',
  18.     [PLang^.LangId, PLang^.CodePage, Name]);
  19.   PValue := VerGetValue(FBuffer, BlockName);
  20.   if PValue = nil then
  21.   begin
  22.     // Error in resource, like TrueImage.exe, where no LangId.
  23.     // Lets try with default langId
  24.     FmtStr(BlockName, '\StringFileInfo\%.4x%.4x\%s',
  25.       [Default.LangId, PLang^.CodePage, Name]);
  26.     PValue := VerGetValue(FBuffer, BlockName);
  27.   end;
  28.   if PValue <> nil then
  29.     Result := UTF8Encode(WideString(PWideChar(PValue)));
  30. end;
Added line [20..27].
Although of course more correct to correct the error. But it is necessary to write to acronis developers.

OLLI_S

  • New member
  • *
  • Posts: 19
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #9 on: July 16, 2018, 10:36:59 am »
Hello ASerge,

Problem in Acronis True Image.
There is it's VersionInfo block:
Code: C  [Select]
  1. 1 VERSIONINFO
  2. FILEVERSION 22,5,1,12510
  3. PRODUCTVERSION 22,5,1,12510
  4. FILEOS 0x4
  5. FILETYPE 0x1
  6. {
  7. BLOCK "StringFileInfo"
  8. {
  9.         BLOCK "040904b0"
  10.         {
  11.                 VALUE "Comments", "http://www.acronis.com/"
  12.                 VALUE "CompanyName", "Acronis International GmbH"
  13.                 VALUE "FileDescription", "Acronis True Image 2018"
  14.                 VALUE "FileVersion", "22,5,1,12510"
  15.                 VALUE "InternalName", "ti_console"
  16.                 VALUE "LegalCopyright", "Copyright (C) Acronis International GmbH, 2002-2017."
  17.                 VALUE "LegalTrademarks", "Acronis International GmbH. All rights reserved."
  18.                 VALUE "OriginalFilename", "ti_console.exe"
  19.                 VALUE "ProductName", "Acronis True Image 2018"
  20.                 VALUE "ProductVersion", "22,5,1,12510"
  21.         }
  22. }
  23.  
  24. BLOCK "VarFileInfo"
  25. {
  26.         VALUE "Translation", 0x0000 0x04B0
  27. }
  28. }
As you can see VarFileInfo=0x0000 0x04B0, but StringFileInfo contains only "040904b0", and the block "000004b0" does not. This is a mistake of developers of acronis.

I am really a noob (beginner) about this topic.
Where can this version-information that you postet be found?
What do thoese Hex-Values (like 0x0000) mean?

I will check the code tonight.
But is this a universal working code (for all applications that have the same issues in the version info)?
Or is this just a fix for Acronis True Image?

Thank you for helping me!

Best regards

OLLI

ASerge

  • Hero Member
  • *****
  • Posts: 827
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #10 on: July 16, 2018, 04:02:41 pm »
Where can this version-information that you postet be found?
What do thoese Hex-Values (like 0x0000) mean?
From documentation https://docs.microsoft.com/en-us/windows/desktop/menurc/versioninfo-resource

Quote
But is this a universal working code (for all applications that have the same issues in the version info)?
Or is this just a fix for Acronis True Image?
This is a fix for errors such as those in Acronis True Image. In normal cases, this is not necessary. Applications are usually developed without taking into account other developers errors, but if the percentage of such errors is large, then add code that takes this into account.

OLLI_S

  • New member
  • *
  • Posts: 19
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #11 on: July 16, 2018, 10:45:13 pm »
Thank you ASerge for the source code, it is working perfectly.
And also thank you for providing the link with additional info.

OLLI_S

  • New member
  • *
  • Posts: 19
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #12 on: July 17, 2018, 09:04:26 pm »
Hello ASerge,

I have one more question about the File Version and the Product Version:

With the following lines I get the File Version and Product Version stings:

Code: Pascal  [Select]
  1.     AppendInfo(CviFileVersion);
  2.     AppendInfo(CviProductVersion);

But there are also the following lines:

Code: Pascal  [Select]
  1.     LV := VerInfo.FileLongVersion;
  2.     Memo1.Append(Format('FileLongVersion=%d.%d.%d.%d', [LV.Words[3], LV.Words[2], LV.Words[1], LV.Words[0]]));
  3.  
  4.     LV := VerInfo.ProductLongVersion;
  5.     Memo1.Append(Format('FileLongVersion=%d.%d.%d.%d', [LV.Words[3], LV.Words[2], LV.Words[1], LV.Words[0]]));

There are sometimes differences between File Version (from first code) and File Version (from second code).
Is it correct that the first file info is the File Version String from the version info and the second is the file version from the application (outside the version info block)?

I am asking because I am looking for a perfect label (caption) for those fields.
The text I write before the values.
Maybe "File Version" and "File Version String" (but I need something better).

Best regards

OLLI

ASerge

  • Hero Member
  • *****
  • Posts: 827
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #13 on: July 18, 2018, 12:07:07 am »
There are sometimes differences between File Version (from first code) and File Version (from second code).
The link above already contains information. These fields are different. A string is a general way of storing data for a version resource, and a numeric one is a dedicated way of storing data for quick access (For example the SysUtils.GetFileVersion reads it). Usually developers make them the same.
Example of *.rc file:
Code: Text  [Select]
  1. #define FileVersionInt 2018,7,18,1
  2. #define FileVersionStr "2018.07.18.1\0"
  3.  
  4. #pragma code_page(1252)
  5. LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
  6. 1 VERSIONINFO
  7. FILEVERSION FileVersionInt
  8. FILEOS VOS_NT_WINDOWS32
  9. FILETYPE VFT_APP
  10. BEGIN
  11.   BLOCK "StringFileInfo"
  12.   BEGIN
  13.     BLOCK "040904E4"
  14.     BEGIN
  15.       VALUE "FileVersion", FileVersionStr
  16. #...
  17.  

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus