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