首页  编辑  

读取预定义的文件版本信息

Tags: /超级猛料/Stream.File.流、文件和目录/文件操作/   Date Created:
Delphi 中读取预定义的文件版本信息
Kingron, 2001-05-02
这个函数很有用的!用于取得文件的版本信息!(我都调试通过了D5   SP1+Win200   SP1)但是有一个地方我无法解决!  
 请注意那个UserDefineValue,必须传入一个字符串,对于用户自定义的来说,这个是不确定的。  
 我的问题是,如何知道用户自定义了那些   字符串版本   信息?  
 type  
     TFileInfo   =   packed   record  
         CommpanyName:   string;  
         FileDescription:   string;  
         FileVersion:   string;  
         InternalName:   string;  
         LegalCopyright:   string;  
         LegalTrademarks:   string;  
         OriginalFileName:   string;  
         ProductName:   string;  
         ProductVersion:   string;  
         Comments:   string;  
         VsFixedFileInfo:VS_FIXEDFILEINFO;  
         UserDefineValue:string;  
     end;  
   
 ///UserDefine就是用户自定义的了,返回值保存在Info.UserDefineValue中  
   
 function   GetFileVersionInfomation(const   FileName:   string;   var   info:   TFileInfo;UserDefine:string=''):  
     boolean;  
 const  
     SFInfo=   '\StringFileInfo\';  
 var  
     VersionInfo:   Pointer;  
     InfoSize:   DWORD;  
     InfoPointer:   Pointer;  
     Translation:   Pointer;  
     VersionValue:   string;  
     unused:   DWORD;  
 begin  
     unused   :=   0;  
     Result   :=   False;  
     InfoSize   :=   GetFileVersionInfoSize(pchar(FileName),   unused);  
     if   InfoSize   >   0   then  
     begin  
         GetMem(VersionInfo,   InfoSize);  
         Result   :=   GetFileVersionInfo(pchar(FileName),   0,   InfoSize,   VersionInfo);  
         if   Result   then  
         begin  
             VerQueryValue(VersionInfo,   '\VarFileInfo\Translation',   Translation,   InfoSize);  
             VersionValue   :=   SFInfo   +   IntToHex(LoWord(Longint(Translation^)),   4)   +  
                 IntToHex(HiWord(Longint(Translation^)),   4)   +   '\';  
             VerQueryValue(VersionInfo,   pchar(VersionValue   +   'CompanyName'),   InfoPointer,   InfoSize);  
             info.CommpanyName   :=   string(pchar(InfoPointer));  
             VerQueryValue(VersionInfo,   pchar(VersionValue   +   'FileDescription'),   InfoPointer,   InfoSize);  
             info.FileDescription   :=   string(pchar(InfoPointer));  
             VerQueryValue(VersionInfo,   pchar(VersionValue   +   'FileVersion'),   InfoPointer,   InfoSize);  
             info.FileVersion   :=   string(pchar(InfoPointer));  
             VerQueryValue(VersionInfo,   pchar(VersionValue   +   'InternalName'),   InfoPointer,   InfoSize);  
             info.InternalName   :=   string(pchar(InfoPointer));  
             VerQueryValue(VersionInfo,   pchar(VersionValue   +   'LegalCopyright'),   InfoPointer,   InfoSize);  
             info.LegalCopyright   :=   string(pchar(InfoPointer));  
             VerQueryValue(VersionInfo,   pchar(VersionValue   +   'LegalTrademarks'),   InfoPointer,   InfoSize);  
             info.LegalTrademarks   :=   string(pchar(InfoPointer));  
             VerQueryValue(VersionInfo,   pchar(VersionValue   +   'OriginalFileName'),   InfoPointer,   InfoSize);  
             info.OriginalFileName   :=   string(pchar(InfoPointer));  
             VerQueryValue(VersionInfo,   pchar(VersionValue   +   'ProductName'),   InfoPointer,   InfoSize);  
             info.ProductName   :=   string(pchar(InfoPointer));  
             VerQueryValue(VersionInfo,   pchar(VersionValue   +   'ProductVersion'),   InfoPointer,   InfoSize);  
             info.ProductVersion   :=   string(pchar(InfoPointer));  
             VerQueryValue(VersionInfo,   pchar(VersionValue   +   'Comments'),   InfoPointer,   InfoSize);  
             info.Comments   :=   string(pchar(InfoPointer));  
             if   VerQueryValue(VersionInfo,   '\',   InfoPointer,   InfoSize)   then  
                 info.VsFixedFileInfo   :=   TVSFixedFileInfo(InfoPointer^);  
             if   UserDefine<>''   then  
             begin  
                 if   VerQueryValue(VersionInfo,pchar(VersionValue+UserDefine),InfoPointer,InfoSize)   then  
                     info.UserDefineValue:=string(pchar(InfoPointer));  
             end;  
         end;  
         FreeMem(VersionInfo);  
     end;  
 end;  
   
 procedure   TForm1.Button1Click(Sender:   TObject);  
 var  
     info:   TFileInfo;  
 begin  
     if   OpenDialog1.Execute   then  
     begin  
         if   GetFileVersionInfomation(opendialog1.FileName,   info,'WOW   Version')   then  
 ////我必须知道'WOW   Version'才能知道有这么一个自定义的串。如果用户定义的是'abc'我就没有办法取得了。  
 ////而资源管理器的版本信息中  
 ///就不一定需要知道。它可以找出所有的版本信息。  
         begin  
             Listbox1.Items.Add(OpenDialog1.FileName);  
             ListBox1.Items.Add('Comments:'   +   info.Comments);  
             ListBox1.Items.Add('CommpanyName:'   +   info.CommpanyName);  
             ListBox1.Items.Add('FileDescription:'   +   info.FileDescription);  
             ListBox1.Items.Add('FileVersion:'   +   info.FileVersion);  
             ListBox1.Items.Add('InternalName:'   +   info.InternalName);  
             ListBox1.Items.Add('LegalCopyright:'   +   info.LegalCopyright);  
             ListBox1.Items.Add('LegalTrademarks:'   +   info.LegalTrademarks);  
             ListBox1.Items.Add('OriginalFileName:'   +   info.OriginalFileName);  
             ListBox1.Items.Add('ProductName:'   +   info.ProductName);  
             ListBox1.Items.Add('ProductVersion:'   +   info.ProductVersion);  
             ListBox1.Items.Add('UserDefineValue:'   +   info.UserDefineValue);  
             if   boolean(info.VsFixedFileInfo.dwFileFlags   and   vs_FF_Debug)   then  
               listbox1.Items.Add('Debug:True')  
               else  
               ListBox1.Items.Add('Debug:False');  
             ListBox1.Items.Add('');    
         end;  
     end;  
 end;  
   
 我就是要做出资源管理其的文件的属性--〉版本中的效果。  
 实际上就是枚举文件的所有的用户自定义的版本信息字符串。  
23 楼GoodHope(好望角)回复于 2001-05-20 21:01:00 得分 0 下面是我抽空写的一个读取全部版本信息的函数,由于工作紧张,没有写释放部分。  
   
 这个函数假定版本信息已经存到一个文件中,其实直接用GetFileVersionInfoSize取得的内容初始化TMemoryStream也是完全可以的。  
type
    TFileInfo = packed record
        CommpanyName: string;
        FileDescription: string;
        FileVersion: string;
        InternalName: string;
        LegalCopyright: string;
        LegalTrademarks: string;
        OriginalFileName: string;
        ProductName: string;
        ProductVersion: string;
        Comments: string;
        VsFixedFileInfo: VS_FIXEDFILEINFO;
        UserDefineValue: string;
    end;

    PAString = ^TAString;

    TAString = packed record
        wLength: WORD;
        wValueLength: WORD;
        wType: WORD;
        szKey: PWCHAR;
        Padding: PWCHAR;
        Value: PWCHAR;
    end;

    PStringTable = ^TStringTable;

    TStringTable = packed record
        wLength: WORD;
        wValueLength: WORD;
        wType: WORD;
        szKey: PWCHAR;
        Padding: PWCHAR;
        Children: array of PAString;
    end;

    PStringFileInfo = ^TStringFileInfo;

    TStringFileInfo = packed record
        wLength: WORD;
        wValueLength: WORD;
        wType: WORD;
        szKey: PWCHAR;
        Padding: PWCHAR;
        Children: array of PStringTable;
    end;

    PAVar = ^TAVar;

    TAVar = packed record
        wLength: WORD;
        wValueLength: WORD;
        wType: WORD;
        szKey: PWCHAR;
        Padding: PWCHAR;
        Value: PWCHAR;
    end;

    PVarFileInfo = ^TVarFileInfo;

    TVarFileInfo = packed record
        wLength: WORD;
        wValueLength: WORD;
        wType: WORD;
        szKey: PWCHAR;
        Padding: PWCHAR;
        Children: array of PAVar;
    end;

    PVSVersionInfo = ^TVSVersionInfo;

    TVSVersionInfo = packed record
        wLength: WORD;
        wValueLength: WORD;
        wType: WORD;
        szKey: PWCHAR;
        Padding1: PWCHAR;
        Value: TVSFixedFileInfo;
        Padding2: PWCHAR;
        StringFileInfo: PStringFileInfo;
        VarFileInfo: PVarFileInfo;
    end;

function LoadVersionInfo(const FileName: string): PVSVersionInfo;
var
    Stream: TMemoryStream;

    function ReadWideString: PWideChar;
    var
        iCount, iSize: Integer;
        Buffer: PWideChar;
        wcTerminal: WideChar;
    begin
        Result := nil;
        Buffer := Pointer(Integer(Stream.Memory) + Stream.Position);
        wcTerminal := #0;
        for iCount := 0 to ((Stream.Size - Stream.Position) div 2) - 1 do
            if Buffer[iCount] = wcTerminal then
            begin
                iSize := Succ(iCount) * SizeOf(WideChar);
                Result := AllocMem(iSize);
                Stream.Read(Result^, iSize);
                Exit;
            end;
    end;

    function AlignToDWord: PWideChar;
    var
        iCount: Integer;
    begin
        iCount := Stream.Position mod 4;
        if iCount = 0 then
            Result := nil
        else
        begin
            Result := AllocMem(((iCount + 1) div 2) * SizeOf(WideChar));
            Stream.Read(Result^, iCount);
        end;
    end;

    function ReadString: PAString;
    begin
        New(Result);
        Stream.Read(Result.wLength, SizeOf(WORD));
        Stream.Read(Result.wValueLength, SizeOf(WORD));
        Stream.Read(Result.wType, SizeOf(WORD));
        Result.szKey := ReadWideString;
        Result.Padding := AlignToDWord;
        Result.Value := ReadWideString;
        AlignToDWord;
    end;

    function ReadStringTable: PStringTable;
    var
        TerminalPos: Integer;
    begin
        TerminalPos := Stream.Position;
        New(Result);
        Stream.Read(Result.wLength, SizeOf(WORD));
        Stream.Read(Result.wValueLength, SizeOf(WORD));
        Stream.Read(Result.wType, SizeOf(WORD));
        Result.szKey := ReadWideString;
        Result.Padding := AlignToDWord;

        Inc(TerminalPos, Result.wLength);
        while Stream.Position < TerminalPos - 1 do
        begin
            SetLength(Result.Children, Length(Result.Children) + 1);
            Result.Children[High(Result.Children)] := ReadString;
        end;
    end;

    function ReadStringFileInfo: PStringFileInfo;
    var
        TerminalPos: Integer;
    begin
        TerminalPos := Stream.Position;
        New(Result);
        Stream.Read(Result.wLength, SizeOf(WORD));
        Stream.Read(Result.wValueLength, SizeOf(WORD));
        Stream.Read(Result.wType, SizeOf(WORD));
        Result.szKey := ReadWideString;
        Result.Padding := AlignToDWord;

        Inc(TerminalPos, Result.wLength);
        while Stream.Position < TerminalPos - 1 do
        begin
            SetLength(Result.Children, Length(Result.Children) + 1);
            Result.Children[High(Result.Children)] := ReadStringTable;
        end;
    end;

    function ReadAVar: PAVar;
    begin
        New(Result);
        Stream.Read(Result.wLength, SizeOf(WORD));
        Stream.Read(Result.wValueLength, SizeOf(WORD));
        Stream.Read(Result.wType, SizeOf(WORD));
        Result.szKey := ReadWideString;
        Result.Padding := AlignToDWord;
        Result.Value := ReadWideString;
        AlignToDWord;
    end;

    function ReadVarFileInfo: PVarFileInfo;
    var
        TerminalPos: Integer;
    begin
        TerminalPos := Stream.Position;
        New(Result);
        Stream.Read(Result.wLength, SizeOf(WORD));
        Stream.Read(Result.wValueLength, SizeOf(WORD));
        Stream.Read(Result.wType, SizeOf(WORD));
        Result.szKey := ReadWideString;
        Result.Padding := AlignToDWord;

        Inc(TerminalPos, Result.wLength);
        while Stream.Position < TerminalPos - 1 do
        begin
            SetLength(Result.Children, Length(Result.Children) + 1);
            Result.Children[High(Result.Children)] := ReadAVar;
        end;
    end;

begin
    New(Result);
    Stream := TMemoryStream.Create;
    Stream.LoadFromFile(FileName);
    Stream.Read(Result.wLength, SizeOf(Result.wLength));
    Stream.Read(Result.wValueLength, SizeOf(Result.wValueLength));
    Stream.Read(Result.wType, SizeOf(Result.wType));
    Result.szKey := ReadWideString;
    Result.Padding1 := AlignToDWord;
    Stream.Read(Result.Value, SizeOf(Result.Value));
    Result.StringFileInfo := ReadStringFileInfo;
    Result.VarFileInfo := ReadVarFileInfo;
    Stream.Free;
end;