0

VerQueryValue()用来获取“PrivateBuild”键的值,这很好用。

除非该值只有一个字符:例如 'b',这对于 beta 版本来说并不罕见。在这种情况下,函数返回False.

我还使用可以读取文件版本的第 3 方 Delphi 程序对此进行了测试(以确保我的文件读取逻辑不是问题):

http://www.delphidabbler.com/articles?article=20

这有同样的问题。

任何人都可以验证这是 Windows 功能的问题VerQueryValue()吗?这也可能是 Delphi XE3 IDE 的问题 - 也许它有一个错误并且没有将单个字符写入 dll 文件版本信息。

4

1 回答 1

1

我可以确认这是 XE3 和 4 中的问题。这似乎是W(Unicode)版本和A(ANSI)版本之间的问题,因为我用来测试 XE3 和 4 正确读取单个字符的 Delphi 2007 中的相同代码PrivateBuild 价值。正如@DavidHeffernan 在评论中提到的那样,这可能是资源编译器的问题,尽管我不确定 32 位资源编译器在 D2007 和 XE 之间是否发生了变化。(在 D2007 中使用具有需要 Unicode 的语言 ID 然后 Unicode 值的资源,因此资源编译器版本支持 Unicode 以及 Ansi。)

测试代码,从我身边的一个旧单元中快速获取,添加到implementation一个新的 VCL 表单应用程序的部分,上面有一个TMemoTButton,并使用正常的 Delphi 对话框快速设置测试版本信息:

type
  TVersionInfo=record
    // Name of company
    CompanyName: string;
    // Description of file
    FileDescription: string;
    // File version
    FileVersion: string;
    // Internal name
    InternalName: string;
    // Legal copyright information
    LegalCopyright: string;
    // Legal trademark information
    LegalTradeMarks: string;
    // Original filename
    OriginalFilename: string;
    // Product name
    ProductName : string;
    // Product version
    ProductVersion: string;
    // Private build
    PrivateBuild: string;
    // Comments
    Comments: string;
  end;

const
  ItemList: array [0..10] of string = ( 'CompanyName',
                                       'FileDescription',
                                       'FileVersion',
                                       'InternalName',
                                       'LegalCopyright',
                                       'LegalTradeMarks',
                                       'OriginalFilename',
                                       'ProductName',
                                       'ProductVersion',
                                       'PrivateBuild',
                                       'Comments' );

function GetVerInfo(const FileName: string; var VersionInfo: TVersionInfo): Boolean;
var
  i: Integer;
  dwLen: Word;
  lpdwHandle: Cardinal;
  pValue: PChar;
  lpData: Pointer;
  uiLen: UInt;
  LCID: string;
begin
  dwLen := GetFileVersionInfoSize(PChar(FileName), lpdwHandle);
  Result := (dwLen > 0);
  if not Result then
    Exit;
  GetMem(lpData, (dwLen + 1) * SizeOf(Char));
  try
    LCID := 'StringFileInfo\' + IntToHex(GetUserDefaultLCID, 4) + IntToHex(GetACP, 4) + '\';

    GetFileVersionInfo(PChar(FileName), 0, dwLen, lpData);
    for i := Low(ItemList) to High(ItemList) do
    begin
      if (VerQueryValue(lpData, PChar(LCID + ItemList[i]), Pointer(pValue), uiLen)) then
        case i of
          0: VersionInfo.CompanyName := pValue;
          1: VersionInfo.FileDescription := pValue;
          2: VersionInfo.FileVersion := pValue;
          3: VersionInfo.InternalName := pValue;
          4: VersionInfo.LegalCopyright := pValue;
          5: VersionInfo.LegalTradeMarks := pValue;
          6: VersionInfo.OriginalFilename := pValue;
          7: VersionInfo.ProductName := pValue;
          8: VersionInfo.ProductVersion := pValue;
          9: VersionInfo.PrivateBuild := pValue;
         10: VersionInfo.Comments := pValue;
        end;

    end;
  finally
    FreeMem(lpData);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  VI: TVersionInfo;
begin
  Memo1.Clear;
  GetVerInfo(ParamStr(0), VI);
  Memo1.Lines.Add('Company name: ' + VI.CompanyName);
  Memo1.Lines.Add('File version: ' + VI.FileVersion);
  Memo1.Lines.Add('Private build: ' + VI.PrivateBuild);

end;
于 2013-06-27T13:48:43.763 回答