This has been described at About:
http://delphi.about.com/cs/adptips2001/a/bltip0701_4.htm Basically, you just use the GetFileVersionInfo function to obtain the data and then VerQueryValue function to read it.
Because these API functions are a bit 'hard' to use, I have written a simple example:
type TEXEVersionData = record CompanyName, FileDescription, FileVersion, InternalName, LegalCopyright, LegalTrademarks, OriginalFileName, ProductName, ProductVersion, Comments, PrivateBuild, SpecialBuild: string; end;
function GetEXEVersionData(const FileName: string): TEXEVersionData; type PLandCodepage = ^TLandCodepage; TLandCodepage = record wLanguage, wCodePage: word; end; var dummy, len: cardinal; buf, pntr: pointer; lang: string; begin len := GetFileVersionInfoSize(PChar(FileName), dummy); if len = 0 then RaiseLastOSError; GetMem(buf, len); try if not GetFileVersionInfo(PChar(FileName), 0, len, buf) then RaiseLastOSError;
if not VerQueryValue(buf, '\VarFileInfo\Translation\', pntr, len) then RaiseLastOSError;
lang := Format('%.4x%.4x', [PLandCodepage(pntr)^.wLanguage, PLandCodepage(pntr)^.wCodePage]);
if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\CompanyName'), pntr, len){ and (@len <> nil)} then result.CompanyName := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\FileDescription'), pntr, len){ and (@len <> nil)} then result.FileDescription := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\FileVersion'), pntr, len){ and (@len <> nil)} then result.FileVersion := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\InternalName'), pntr, len){ and (@len <> nil)} then result.InternalName := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\LegalCopyright'), pntr, len){ and (@len <> nil)} then result.LegalCopyright := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\LegalTrademarks'), pntr, len){ and (@len <> nil)} then result.LegalTrademarks := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\OriginalFileName'), pntr, len){ and (@len <> nil)} then result.OriginalFileName := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\ProductName'), pntr, len){ and (@len <> nil)} then result.ProductName := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\ProductVersion'), pntr, len){ and (@len <> nil)} then result.ProductVersion := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\Comments'), pntr, len){ and (@len <> nil)} then result.Comments := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\PrivateBuild'), pntr, len){ and (@len <> nil)} then result.PrivateBuild := PChar(pntr); if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\SpecialBuild'), pntr, len){ and (@len <> nil)} then result.SpecialBuild := PChar(pntr); finally FreeMem(buf); end; end; Try it. But beware -- currently, this only works for en-us EXEs! It doesn't work for most of the EXEs on my Swedish machine, for instance. It is late now; tomorrow I will extend this to work with any EXE language, if only I get some time left. [The About.com code has the same problem, but they don't even pretend it is a problem!]
Update: The code now works with any EXE language.
http://stackoverflow.com/questions/5539316/how-can-i-read-details-of-file
http://stackoverflow.com/questions/17340794/verqueryvalue-does-not-work-with-single-character-values
http://stackoverflow.com/questions/6557778/get-fileversion-with-build
|
请发表评论