fileinfo.pp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {
  12. Based on getver by Bernd Juergens - Munich, Germany
  13. email :[email protected]
  14. Usage : Drop component on form. Set desired file name using
  15. FileVersionInfo.filename := 'c:\winnt\system32\comctl32.dll'
  16. or something like that.
  17. Read StringLists VersionStrings and VersionCategories.
  18. or check a single entry:
  19. FileVersionInfo1.fileName := 'd:\winnt\system32\comctl32.dll';
  20. showMessage(FileVersionInfo1.getVersionSetting('ProductVersion'));
  21. }
  22. unit fileinfo;
  23. {$mode objfpc}
  24. interface
  25. uses
  26. Windows, SysUtils, Classes;
  27. { Record to receive charset }
  28. type TTranslation = record
  29. langID : WORD;
  30. charset : WORD;
  31. end;
  32. type
  33. TFileVersionInfo = class(TComponent)
  34. private
  35. FFileName : String;
  36. FmyVersionStrings : TStringList;
  37. FmyVersionCategories : TStringList;
  38. procedure SetFileName (inp : string);
  39. procedure readVersionFromFile;
  40. protected
  41. public
  42. constructor Create(AOwner: TComponent); override;
  43. destructor Destroy; override;
  44. function getVersionSetting(inp : string): String;
  45. published
  46. property fileName : string read FFileName write SetFileName;
  47. property VersionStrings : TStringList read FmyVersionStrings;
  48. property VersionCategories : TStringList read FmyVersionCategories;
  49. end;
  50. implementation
  51. { initialize everything }
  52. constructor TFileVersionInfo.Create(AOwner: TComponent);
  53. begin
  54. inherited Create(AOwner);
  55. FmyVersionStrings := TStringList.Create;
  56. FmyVersionCategories := TStringList.Create;
  57. FFileName := '';
  58. end;
  59. destructor TFileVersionInfo.Destroy;
  60. begin
  61. FmyVersionCategories.Free;
  62. FmyVersionStrings.Free;
  63. inherited;
  64. end;
  65. { Get filename, check if file exists and read info from file }
  66. procedure TFileVersionInfo.SetFileName (inp : string);
  67. begin
  68. FmyVersionStrings.clear;
  69. FmyVersionCategories.clear;
  70. if fileexists(inp) then
  71. begin
  72. FFileName := inp;
  73. readVersionFromFile;
  74. end
  75. else
  76. begin
  77. FFileName := '';
  78. end;
  79. end;
  80. { read info from file }
  81. procedure TFileVersionInfo.readVersionFromFile;
  82. var struSize : Dword;
  83. dwBytes,someDummy : Dword;
  84. a,txt : array[0..256] of char;
  85. p : pchar;
  86. i : integer;
  87. pp : pointer;
  88. theFixedInfo : TVSFixedFileInfo;
  89. theTrans : TTranslation;
  90. s : string;
  91. ts : TStringList;
  92. begin
  93. ts := TStringList.Create;
  94. try
  95. ts.add('CompanyName');
  96. ts.add('FileDescription');
  97. ts.add('FileVersion');
  98. ts.add('InternalName');
  99. ts.add('LegalCopyright');
  100. ts.add('OriginalFilename');
  101. ts.add('ProductName');
  102. ts.add('ProductVersion');
  103. strPCopy(a,FFileName);
  104. { get size of data }
  105. struSize := GetFileVersionInfoSize(a,@someDummy);
  106. if struSize=0 then exit;
  107. p := NIL;
  108. try
  109. { get memory }
  110. GetMem(p,struSize+10);
  111. { get data }
  112. if not GetFileVersionInfo(a,0,struSize,p) then exit;
  113. { get root info }
  114. if not VerQueryValue(p,'\',pp,dwBytes) then exit;
  115. move(pp^,theFixedInfo,dwBytes);
  116. { get translation info }
  117. if not VerQueryValue(p,'\VarFileInfo\Translation',pp,dwBytes) then
  118. exit;
  119. move(pp^,theTrans,dwBytes);
  120. { iterate over defined items }
  121. for i:=0 to ts.count-1 do
  122. begin
  123. s := '\StringFileInfo\'+inttohex(theTrans.langID,4)+inttohex(theTrans.charset,4)+'\'+ts[i];
  124. StrPCopy(a,s);
  125. if not VerQueryValue(p,a,pp,dwBytes) then Continue;
  126. if dwBytes>0 then
  127. begin
  128. move(pp^,txt,dwBytes);
  129. FmyVersionCategories.add(ts[i]);
  130. FmyVersionStrings.add(StrPas(txt));
  131. end
  132. end;
  133. finally
  134. { release memory }
  135. FreeMem(p);
  136. end;
  137. finally ts.Free end;
  138. end;
  139. { get single version string }
  140. function TFileVersionInfo.getVersionSetting(inp : string): String;
  141. var i : integer;
  142. begin
  143. inp:=LowerCase(inp);
  144. for i:= 0 to FmyVersionCategories.Count -1 do
  145. if LowerCase(FmyVersionCategories[i])=inp then
  146. begin
  147. result := FmyVersionStrings[i];
  148. Exit;
  149. end;
  150. result := '';
  151. end;
  152. end.
  153. {
  154. $Log$
  155. Revision 1.5 2003-07-26 16:23:05 michael
  156. corrected by Michalis:
  157. * VerQueryValue parameters (last parameter should be dwBytes instead of
  158. @dwBytes; you can call
  159. VerQueryValue(...,pp,dwBytes) or
  160. VerQueryValue(...,@pp,@dwBytes) but NOT
  161. VerQueryValue(...,pp,@dwBytes) (and that was the case) )
  162. * corrected
  163. if not VerQueryValue(p,a,pp,dwBytes) then Exit;
  164. to
  165. if not VerQueryValue(p,a,pp,dwBytes) then Continue;
  166. (when some info is missing the code should skip to the next info,
  167. not exit)
  168. + added destructor to Free FmyVersionStrings and FmyVersionCategories objects
  169. to avoid memory leaks
  170. + added ts.Free (and embedded some code in try..finally..end clause)
  171. to avoid memory leaks
  172. * inherited Create should be called at the beginning of constructor
  173. (it's just a good coding practice)
  174. * getVersionSetting re-written, optimised a little (LowerCase(inp) only once;
  175. this function is not supposed to be really "optimised" but this little
  176. improvement was so simple...) (note: when TStringList.CaseSensitive will
  177. be implemented in FPC, this function can be implemented even simpler,
  178. just by calling FmyVersionCategories.IndexOf)
  179. Revision 1.4 2002/09/07 15:15:29 peter
  180. * old logs removed and tabs fixed
  181. }