Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何确定Delphi应用程序版本_Delphi_Version - Fatal编程技术网

如何确定Delphi应用程序版本

如何确定Delphi应用程序版本,delphi,version,Delphi,Version,希望从中获取Delphi应用程序版本号并发布到标题栏 使用此函数可以获取文件的版本,其中包含 版本资源。通过这种方式,您可以显示应用程序的版本号 信息对话框中的应用程序。要将版本资源包括到 在Delphi应用程序中,在项目选项中设置“Versioninfo” 将EXE的完整文件名传递给此函数,它将返回如下字符串: 2.1.5.9或任何您的版本 定义后,您可以使用它设置表单标题,如下所示: procedure TForm1.FormShow(Sender: TObject); begin /

希望从中获取Delphi应用程序版本号并发布到标题栏

使用此函数可以获取文件的版本,其中包含 版本资源。通过这种方式,您可以显示应用程序的版本号 信息对话框中的应用程序。要将版本资源包括到 在Delphi应用程序中,在项目选项中设置“Versioninfo”


将EXE的完整文件名传递给此函数,它将返回如下字符串: 2.1.5.9或任何您的版本

定义后,您可以使用它设置表单标题,如下所示:

procedure TForm1.FormShow(Sender: TObject);
begin 
  //ParamStr(0) is the full path and file name of the current application
  Form1.Caption := Form1.Caption + ' version ' + GetFileVersion(ParamStr(0));
end;

我是这样做的。我在几乎所有的小型实用程序中都用到了这个:

procedure GetBuildInfo(var V1, V2, V3, V4: word);
var
  VerInfoSize, VerValueSize, Dummy: DWORD;
  VerInfo: Pointer;
  VerValue: PVSFixedFileInfo;
begin
  VerInfoSize := GetFileVersionInfoSize(PChar(ParamStr(0)), Dummy);
  if VerInfoSize > 0 then
  begin
      GetMem(VerInfo, VerInfoSize);
      try
        if GetFileVersionInfo(PChar(ParamStr(0)), 0, VerInfoSize, VerInfo) then
        begin
          VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize);
          with VerValue^ do
          begin
            V1 := dwFileVersionMS shr 16;
            V2 := dwFileVersionMS and $FFFF;
            V3 := dwFileVersionLS shr 16;
            V4 := dwFileVersionLS and $FFFF;
          end;
        end;
      finally
        FreeMem(VerInfo, VerInfoSize);
      end;
  end;
end;

function GetBuildInfoAsString: string;
var
  V1, V2, V3, V4: word;
begin
  GetBuildInfo(V1, V2, V3, V4);
  Result := IntToStr(V1) + '.' + IntToStr(V2) + '.' +
    IntToStr(V3) + '.' + IntToStr(V4);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.Caption := Form1.Caption + ' - v' + GetBuildInfoAsString;
end;

如果您想知道当前正在运行的可执行文件的版本,我强烈建议不要使用GetFileVersion!我有两个很好的理由这样做:

  • 可执行文件可能不可访问(断开驱动器/共享连接),或已更改(.exe重命名为.bak并替换为新的.exe,而不停止正在运行的进程)
  • 您试图读取的版本数据实际上已经加载到内存中,并且可以通过加载此资源来使用,这总比执行额外(相对较慢)的磁盘操作要好
  • 要在Delphi中加载版本资源,我使用如下代码:

    uses Windows,Classes,SysUtils;
    var
      verblock:PVSFIXEDFILEINFO;
      versionMS,versionLS:cardinal;
      verlen:cardinal;
      rs:TResourceStream;
      m:TMemoryStream;
      p:pointer;
      s:cardinal;
    begin
      m:=TMemoryStream.Create;
      try
        rs:=TResourceStream.CreateFromID(HInstance,1,RT_VERSION);
        try
          m.CopyFrom(rs,rs.Size);
        finally
          rs.Free;
        end;
        m.Position:=0;
        if VerQueryValue(m.Memory,'\',pointer(verblock),verlen) then
          begin
            VersionMS:=verblock.dwFileVersionMS;
            VersionLS:=verblock.dwFileVersionLS;
            AppVersionString:=Application.Title+' '+
              IntToStr(versionMS shr 16)+'.'+
              IntToStr(versionMS and $FFFF)+'.'+
              IntToStr(VersionLS shr 16)+'.'+
              IntToStr(VersionLS and $FFFF);
          end;
        if VerQueryValue(m.Memory,PChar('\\StringFileInfo\\'+
          IntToHex(GetThreadLocale,4)+IntToHex(GetACP,4)+'\\FileDescription'),p,s) or
            VerQueryValue(m.Memory,'\\StringFileInfo\\040904E4\\FileDescription',p,s) then //en-us
              AppVersionString:=PChar(p)+' '+AppVersionString;
      finally
        m.Free;
      end;
    end;
    

    我们对所有应用程序都这样做,但我们使用Raize组件RzVersioninfo。 工作非常好,只需要使用以下代码

    关于表单创建

    标题:=rzVersionInfo.FileDescription+':'+rzVersionInfo.FileVersion


    显然,如果您不想从raize获得任何其他组件,请使用上面的选项之一,因为raize组件是有成本的。

    多亏了上面的文章,我为此制作了自己的库

    我相信它比这里的所有其他解决方案都要正确一点,所以我与大家分享它-可以随意重用它

    unit KkVersion;
    
    interface
    
    function FileDescription: String;
    function LegalCopyright: String;
    function DateOfRelease: String; // Proprietary
    function ProductVersion: String;
    function FileVersion: String;
    
    implementation
    
    uses
      Winapi.Windows, System.SysUtils, System.Classes, Math;
    
    (*
      function GetHeader(out AHdr: TVSFixedFileInfo): Boolean;
    
      var
      BFixedFileInfo: PVSFixedFileInfo;
      RM: TMemoryStream;
      RS: TResourceStream;
      BL: Cardinal;
    
      begin
      Result := False;
      RM := TMemoryStream.Create;
      try
      RS := TResourceStream.CreateFromID(HInstance, 1, RT_VERSION);
      try
      RM.CopyFrom(RS, RS.Size);
      finally
      FreeAndNil(RS);
      end;
    
      // Extract header
      if not VerQueryValue(RM.Memory, '\\', Pointer(BFixedFileInfo), BL) then
      Exit;
    
      // Prepare result
      CopyMemory(@AHdr, BFixedFileInfo, Math.Min(sizeof(AHdr), BL));
      Result := True;
      finally
      FreeAndNil(RM);
      end;
      end;
    *)
    
    function GetVersionInfo(AIdent: String): String;
    
    type
      TLang = packed record
        Lng, Page: WORD;
      end;
    
      TLangs = array [0 .. 10000] of TLang;
    
      PLangs = ^TLangs;
    
    var
      BLngs: PLangs;
      BLngsCnt: Cardinal;
      BLangId: String;
      RM: TMemoryStream;
      RS: TResourceStream;
      BP: PChar;
      BL: Cardinal;
      BId: String;
    
    begin
      // Assume error
      Result := '';
    
      RM := TMemoryStream.Create;
      try
        // Load the version resource into memory
        RS := TResourceStream.CreateFromID(HInstance, 1, RT_VERSION);
        try
          RM.CopyFrom(RS, RS.Size);
        finally
          FreeAndNil(RS);
        end;
    
        // Extract the translations list
        if not VerQueryValue(RM.Memory, '\\VarFileInfo\\Translation', Pointer(BLngs), BL) then
          Exit; // Failed to parse the translations table
        BLngsCnt := BL div sizeof(TLang);
        if BLngsCnt <= 0 then
          Exit; // No translations available
    
        // Use the first translation from the table (in most cases will be OK)
        with BLngs[0] do
          BLangId := IntToHex(Lng, 4) + IntToHex(Page, 4);
    
        // Extract field by parameter
        BId := '\\StringFileInfo\\' + BLangId + '\\' + AIdent;
        if not VerQueryValue(RM.Memory, PChar(BId), Pointer(BP), BL) then
          Exit; // No such field
    
        // Prepare result
        Result := BP;
      finally
        FreeAndNil(RM);
      end;
    end;
    
    function FileDescription: String;
    begin
      Result := GetVersionInfo('FileDescription');
    end;
    
    function LegalCopyright: String;
    begin
      Result := GetVersionInfo('LegalCopyright');
    end;
    
    function DateOfRelease: String;
    begin
      Result := GetVersionInfo('DateOfRelease');
    end;
    
    function ProductVersion: String;
    begin
      Result := GetVersionInfo('ProductVersion');
    end;
    
    function FileVersion: String;
    begin
      Result := GetVersionInfo('FileVersion');
    end;
    
    end.
    
    单元版本;
    接口
    函数FileDescription:字符串;
    函数LegalCopyright:字符串;
    函数DateOfRelease:String;//专有的
    函数ProductVersion:字符串;
    函数FileVersion:String;
    实施
    使用
    Windows,System.SysUtils,System.Classes,Math;
    (*
    函数GetHeader(out-AHdr:TVSFixedFileInfo):布尔值;
    变量
    BFixedFileInfo:PVSFixedFileInfo;
    RM:TMemoryStream;
    RS:TResourceStream;
    BL:红衣主教;
    开始
    结果:=假;
    RM:=TMemoryStream.Create;
    尝试
    RS:=TResourceStream.CreateFromID(HInstance,1,RT_版本);
    尝试
    RM.CopyFrom(卢比,卢比尺寸);
    最后
    自由零(RS);
    结束;
    //提取头
    如果不是VerQueryValue(RM.Memory,'\\',指针(BFixedFileInfo),BL),则
    出口
    //准备结果
    CopyMemory(@AHdr,BFixedFileInfo,Math.Min(sizeof(AHdr),BL));
    结果:=真;
    最后
    自由零(RM);
    结束;
    结束;
    *)
    函数GetVersionInfo(助手:字符串):字符串;
    类型
    TLang=压缩记录
    液化天然气,页码:WORD;
    结束;
    TLang=TLang的数组[0..10000];
    计划=^t计划;
    变量
    BLNG:计划;
    BLngsCnt:红衣主教;
    布兰吉德:字符串;
    RM:TMemoryStream;
    RS:TResourceStream;
    BP:PChar;
    BL:红衣主教;
    出价:字符串;
    开始
    //假定错误
    结果:='';
    RM:=TMemoryStream.Create;
    尝试
    //将版本资源加载到内存中
    RS:=TResourceStream.CreateFromID(HInstance,1,RT_版本);
    尝试
    RM.CopyFrom(卢比,卢比尺寸);
    最后
    自由零(RS);
    结束;
    //提取翻译列表
    如果不是VerQueryValue(RM.Memory,'\\VarFileInfo\\Translation',指针(BLngs),BL),则
    退出;//无法分析翻译表
    BLngsCnt:=BL分区大小(TLang);
    
    如果BLngsCnt链接不错,但回答很糟糕。请总结一下链接的内容:我们希望通过链接找到什么样的解决方案,需要注意的重要功能是什么?Mick,你应该像Joseph一样检查返回的VerInfoSize,并且只在>0时才进行搜索,因为它可能没有文件版本信息。对于GetMem/freemi来说,try…finally也不坏。我刚刚添加了try…finally.Mick,因为我可以看到您的代码不会编译,因为您的代码段中没有sFileName变量的声明。Joseph,你应该试着保护你的AllocMem。。。finally@Wodzu:它在D2007中对我有效。您的项目是否在项目->选项->版本信息下选中了“在项目中包含版本信息”选项?Windows资源管理器告诉您文件版本是什么?除非您的区域设置是$0409(美国英语),否则这不起作用-这不是一个可靠的假设,在Delphi 10.1(柏林)中工作得很好:)@达维博特曼,你说得对,谢谢你指出这一点。用户Jiri Krivanek有下面的另一个版本,它声称可以避免语言环境问题。我还没试过,但它可能更适合你。或者,您可以将我的代码中的“040904E4”更改为您需要的语言环境。我看到大多数建议的答案都使用GetFileVersion。此选项存在问题,我已在自己的答案中发布了详细信息。如果您在内存和资源分配方面使代码异常安全,我将对此进行投票。我添加了try finally,应该这样做。如果您想知道TMemoryStream的用途:VerQueryValue在读取rs.Memory目录时遇到问题……重命名正在运行的可执行文件没有什么不寻常的,这是Windows无法覆盖它的公认解决方法。更新例程通常会重命名正在运行的可执行文件,以便能够将新版本复制到原始位置。您请求的资源的
    名称是
    PChar(1)
    。如果未找到资源(即没有版本信息),Delphi将尝试抛出
    EResNotFound
    (未找到资源%s)。当它尝试使用
    PChar
    0x00000001
    构建字符串时,它将触发访问冲突,因为没有ansi字符
    unit KkVersion;
    
    interface
    
    function FileDescription: String;
    function LegalCopyright: String;
    function DateOfRelease: String; // Proprietary
    function ProductVersion: String;
    function FileVersion: String;
    
    implementation
    
    uses
      Winapi.Windows, System.SysUtils, System.Classes, Math;
    
    (*
      function GetHeader(out AHdr: TVSFixedFileInfo): Boolean;
    
      var
      BFixedFileInfo: PVSFixedFileInfo;
      RM: TMemoryStream;
      RS: TResourceStream;
      BL: Cardinal;
    
      begin
      Result := False;
      RM := TMemoryStream.Create;
      try
      RS := TResourceStream.CreateFromID(HInstance, 1, RT_VERSION);
      try
      RM.CopyFrom(RS, RS.Size);
      finally
      FreeAndNil(RS);
      end;
    
      // Extract header
      if not VerQueryValue(RM.Memory, '\\', Pointer(BFixedFileInfo), BL) then
      Exit;
    
      // Prepare result
      CopyMemory(@AHdr, BFixedFileInfo, Math.Min(sizeof(AHdr), BL));
      Result := True;
      finally
      FreeAndNil(RM);
      end;
      end;
    *)
    
    function GetVersionInfo(AIdent: String): String;
    
    type
      TLang = packed record
        Lng, Page: WORD;
      end;
    
      TLangs = array [0 .. 10000] of TLang;
    
      PLangs = ^TLangs;
    
    var
      BLngs: PLangs;
      BLngsCnt: Cardinal;
      BLangId: String;
      RM: TMemoryStream;
      RS: TResourceStream;
      BP: PChar;
      BL: Cardinal;
      BId: String;
    
    begin
      // Assume error
      Result := '';
    
      RM := TMemoryStream.Create;
      try
        // Load the version resource into memory
        RS := TResourceStream.CreateFromID(HInstance, 1, RT_VERSION);
        try
          RM.CopyFrom(RS, RS.Size);
        finally
          FreeAndNil(RS);
        end;
    
        // Extract the translations list
        if not VerQueryValue(RM.Memory, '\\VarFileInfo\\Translation', Pointer(BLngs), BL) then
          Exit; // Failed to parse the translations table
        BLngsCnt := BL div sizeof(TLang);
        if BLngsCnt <= 0 then
          Exit; // No translations available
    
        // Use the first translation from the table (in most cases will be OK)
        with BLngs[0] do
          BLangId := IntToHex(Lng, 4) + IntToHex(Page, 4);
    
        // Extract field by parameter
        BId := '\\StringFileInfo\\' + BLangId + '\\' + AIdent;
        if not VerQueryValue(RM.Memory, PChar(BId), Pointer(BP), BL) then
          Exit; // No such field
    
        // Prepare result
        Result := BP;
      finally
        FreeAndNil(RM);
      end;
    end;
    
    function FileDescription: String;
    begin
      Result := GetVersionInfo('FileDescription');
    end;
    
    function LegalCopyright: String;
    begin
      Result := GetVersionInfo('LegalCopyright');
    end;
    
    function DateOfRelease: String;
    begin
      Result := GetVersionInfo('DateOfRelease');
    end;
    
    function ProductVersion: String;
    begin
      Result := GetVersionInfo('ProductVersion');
    end;
    
    function FileVersion: String;
    begin
      Result := GetVersionInfo('FileVersion');
    end;
    
    end.