代码之家  ›  专栏  ›  技术社区  ›  Soon Santos

Delphi可执行版本始终返回相同的值

  •  0
  • Soon Santos  · 技术社区  · 5 年前

    我正在尝试获取正在运行的可执行文件的版本,以便知道我的应用程序何时更改为具有新功能的新版本。

    我使用以下代码获取版本:

    function GetVersaoExe: string;
    type
       PFFI = ^vs_FixedFileInfo;
    var
       F : PFFI;
       Handle : Dword;
       Len : Longint;
       Data : Pchar;
       Buffer : Pointer;
       Tamanho : Dword;
       Parquivo: Pchar;
       Arquivo : string;
    begin
       Arquivo := Application.ExeName;
       Parquivo := StrAlloc(Length(Arquivo) + 1);
       StrPcopy(Parquivo, Arquivo);
       Len := GetFileVersionInfoSize(Parquivo, Handle);
       ShowMessage(IntToStr(Len));
       Result := '';
       if Len > 0 then
       begin
          Data:=StrAlloc(Len+1);
          if GetFileVersionInfo(Parquivo,Handle,Len,Data) then
          begin
             VerQueryValue(Data, '\',Buffer,Tamanho);
             F := PFFI(Buffer);
             Result := Format('%d.%d.%d.%d',
             [HiWord(F^.dwFileVersionMs),
             LoWord(F^.dwFileVersionMs),
             HiWord(F^.dwFileVersionLs),
             Loword(F^.dwFileVersionLs)]
             );
          end;
          StrDispose(Data);
       end;
       StrDispose(Parquivo);
    end;
    

    这将返回号码 4.0.1.1 .

    问题是,我使用这个函数已经有一段时间了,它从来没有改变过这个数字,它总是 4.0.1.1 ,我需要一个每次重建应用程序时都会更改的数字,以知道自上次构建以来发生了变化。

    我检查了其他三种获取版本号的方法,它们碰巧都是一样的 事情。

    有一个 similiar question on StackOverFlow 但我仍然不知道它是否有效。我检查了这个问题,并试图使用他们的方式,但还有另一个问题。当我导入时 ToolsAPI 在我的使用单位中使用 IOTAProjectOptionsConfigurations 并给出以下错误: Cannot compile unit ToolsAPI .

    最后,我试图解决最后一个问题,但我做不到。

    0 回复  |  直到 5 年前
        1
  •  5
  •   Remy Lebeau    5 年前

    只需配置您的项目,使其在每次新构建时自动递增版本号。这个 Version Info “项目选项”页面中有一个用于此目的的复选框。


    也就是说,在你展示的代码中,你不需要使用 StrAlloc() / StrDispose() 完全。只需通过 PChar(Arquivo) 作为输入 GetFileVersionInfoSize() GetFileVersionInfo() ,并更改 Data 到a array of Byte (或 TBytes 如果你的Delphi版本有它)使用 SetLength() 分配它并让编译器自动释放它。

    function GetVersao(const Arquivo: String): string;
    type
      PFFI = ^vs_FixedFileInfo;
    var
      F : PFFI;
      Handle : Dword;
      Len : Longint;
      Data : array of Byte; // or TBytes
      Buffer : Pointer;
      Tamanho : Dword;
    begin
      Result := '';
      Len := GetFileVersionInfoSize(PChar(Arquivo), Handle);
      ShowMessage(IntToStr(Len));
      if Len > 0 then
      begin
        SetLength(Data, Len);
        if GetFileVersionInfo(PChar(Arquivo), Handle, Len, PByte(Data)) then
        begin
          if VerQueryValue(PByte(Data), '\', Buffer, Tamanho) then
          begin
            F := PFFI(Buffer);
            Result := Format('%d.%d.%d.%d',
              [HiWord(F^.dwFileVersionMs),
              LoWord(F^.dwFileVersionMs),
              HiWord(F^.dwFileVersionLs),
              Loword(F^.dwFileVersionLs)]
            );
          end;
        end;
      end;
    end;
    
    function GetVersaoExe: string;
    begin
      Result := GetVersao(Application.ExeName);
    end;
    

    如果你真的想变得圆滑,你甚至不需要使用 GetFileVersionInfo/Size() 完全。您可以使用 (Find|Load|Lock)Resource() 访问调用进程的 RT_VERSION 直接使用资源:

    function GetVersao(Module: THandle): string;
    type
      PFFI = ^vs_FixedFileInfo;
    var
      F : PFFI;
      Len : Longint;
      Data : array of Byte; // or TBytes
      Buffer : Pointer;
      Tamanho : Dword;
      hRes, hResData: THandle;
    begin
      Result := '';
      hRes := FindResource(Module, MAKEINTRESOURCE(1), RT_VERSION);
      Len := SizeOfResource(hRes);
      ShowMessage(IntToStr(Len));
      if Len > 0 then
      begin
        hResData := LoadResource(Module, hRes);
        Buffer := LockResource(hResData);
        SetLength(Data, Len);
        Move(Buffer^, Data[0], Len);
        if VerQueryValue(PByte(Data), '\', Buffer, Tamanho) then
        begin
          F := PFFI(Buffer);
          Result := Format('%d.%d.%d.%d',
            [HiWord(F^.dwFileVersionMs),
            LoWord(F^.dwFileVersionMs),
            HiWord(F^.dwFileVersionLs),
            Loword(F^.dwFileVersionLs)]
          );
        end;
      end;
    end;
    
    function GetVersaoExe: string;
    begin
      Result := GetVersao(GetModuleHandle(nil));
    end;