Recent

Author Topic: [Solved] Exception in TFileVersionInfo.ReadFileInfo  (Read 6692 times)

Thaddy

  • Hero Member
  • *****
  • Posts: 7819
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #15 on: November 12, 2018, 04:36:01 pm »
Indeed, a filesize of 0 is a legal filesize and will not immediately set an Os Error. This is actually a bit undefined I guess.
Ad Brexinitum (can't help it)

lucamar

  • Hero Member
  • *****
  • Posts: 1286
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #16 on: November 12, 2018, 04:57:57 pm »
According to Microsoft's doc:

Quote
If the function fails, the return value is zero. To get extended error information, call GetLastError.

The most probable cause for the function to fail is that the executable has no version info but there are others: You should check the error info and act in consequence.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 1.8.4 & 2.0.2 w/FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

Thaddy

  • Hero Member
  • *****
  • Posts: 7819
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #17 on: November 12, 2018, 05:05:21 pm »
The most probable cause for the function to fail is that the executable has no version info but there are others: You should check the error info and act in consequence.
Which it doesn't properly. Right? It should only raise if there is actually an error.
Ad Brexinitum (can't help it)

OLLI_S

  • Full Member
  • ***
  • Posts: 111
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #18 on: November 17, 2018, 05:30:45 pm »
Hello,

According to Microsoft's doc:

Quote
If the function fails, the return value is zero. To get extended error information, call GetLastError.

The most probable cause for the function to fail is that the executable has no version info but there are others: You should check the error info and act in consequence.

I am not a good programmer, what must be changed in ReadVersionInfo?

Best regards

OLLI

ASerge

  • Hero Member
  • *****
  • Posts: 1187
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #19 on: November 17, 2018, 05:57:06 pm »
I am not a good programmer, what must be changed in ReadVersionInfo?
Nothing.
There may be several reasons why version information is not available. Simply does not exist, or no access, etc. So that generation of errors and transfer to a higher code - the right thing. If you do not want to show this to the user - catch, output to the log, and show the user that there is no data.

OLLI_S

  • Full Member
  • ***
  • Posts: 111
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #20 on: November 17, 2018, 06:30:48 pm »
Hello Aserge,

I added a try ... except block:

Code: Pascal  [Select]
  1.     try
  2.       // Create the Version Information
  3.       VerInfo := TVersionInfo.Create(AppFileName);
  4.     except
  5.       // will only be executed in case of an exception
  6.       on E: Exception do begin
  7.         ShowMessage( 'Error: '+ E.ClassName + #13#10 + E.Message );
  8.         VerInfo.Free;
  9.         exit;
  10.       end;
  11.     end;  

When I select an application that causes problems I see the error message (as expected).
But I also get an Access-Violation message.

So maybe I have to add the try block in TVersionInfo.ReadVersionInfo ?
Or should I modify TVersionInfo.ReadVersionInfo so when the size is zero, that I don't call RaiseLastOSError but show a message and exit?

OLLI
« Last Edit: November 17, 2018, 06:43:07 pm by OLLI_S »

lucamar

  • Hero Member
  • *****
  • Posts: 1286
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #21 on: November 17, 2018, 07:29:35 pm »
When I select an application that causes problems I see the error message (as expected).
But I also get an Access-Violation message.

So maybe I have to add the try block in TVersionInfo.ReadVersionInfo ?
Or should I modify TVersionInfo.ReadVersionInfo so when the size is zero, that I don't call RaiseLastOSError but show a message and exit?

The access violation probably comes from the fact that since, indirectly, ReadVersionInfo is called from the constructor, an exception will prevent the constructor from finalizing, so your call to VerInfo.Free catchs the object at an ... "incovenient" moment :)

To avoid it, you have some options but the best, IMHO, is to modify how TVersionInfo works. The needed changes are rather few and small:

  • Change TVersionInfo.Create() to also set FBuffer to Nil.
  • Delete the call to ReadVersionInfo from TVersionInfo.SetFileName.
  • At the beginning of methods that use FBuffer (GetFixedFileInfo and GetVerValue) add this guard:
    if FBuffer = Nil then ReadVersionInfo;

The basic effect of the changes is to defer doing anything until it is actually needed, instead of proactively doing it as soon as possible; which incidentally prevents raising exceptions until we are actually ready to catch them. Just a question of tastes ;D

ETA Incidentally, if I were you I wouldn't call that class TVersionInfo but TAltVersionInfo or something like that, since there is already a class TVersionInfo in the Fileinfo unit.
« Last Edit: November 17, 2018, 07:33:33 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 1.8.4 & 2.0.2 w/FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

ASerge

  • Hero Member
  • *****
  • Posts: 1187
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #22 on: November 17, 2018, 08:39:16 pm »
I added a try ... except block:
Code: Pascal  [Select]
  1.     try
  2.       // Create the Version Information
  3.       VerInfo := TVersionInfo.Create(AppFileName);
  4.     except
  5.       // will only be executed in case of an exception
  6.       on E: Exception do begin
  7.         ShowMessage( 'Error: '+ E.ClassName + #13#10 + E.Message );
  8.         VerInfo.Free;
  9.         exit;
  10.       end;
  11.     end;  

When I select an application that causes problems I see the error message (as expected).
But I also get an Access-Violation message.
Bad code: release object not in finally, but in the except block. When an exception occurs, the constructor calls the destructor and then you use Free again.
Use right construction:
Code: Pascal  [Select]
  1. try
  2.   VerInfo := TVersionInfo.Create(AppFileName);
  3.   try
  4.     // Do something with version
  5.   finally
  6.     VerInfo.Free;
  7.   end;
  8. except
  9.   on E: Exception do
  10.     ShowMessage( 'Error: '+ E.Message);
  11. end;

OLLI_S

  • Full Member
  • ***
  • Posts: 111
Re: Exception in TFileVersionInfo.ReadFileInfo
« Reply #23 on: February 10, 2019, 02:37:28 pm »
Hello ASerge,

Bad code: release object not in finally, but in the except block. When an exception occurs, the constructor calls the destructor and then you use Free again.
Use right construction:
Code: Pascal  [Select]
  1. try
  2.   VerInfo := TVersionInfo.Create(AppFileName);
  3.   try
  4.     // Do something with version
  5.   finally
  6.     VerInfo.Free;
  7.   end;
  8. except
  9.   on E: Exception do
  10.     ShowMessage( 'Error: '+ E.Message);
  11. end;

Thank you for your correction of the code.
I now catch the exception and show an Information-Message.
So the problem is solved.

Best regards

OLLI