Delphi10.2中如何使用ToolsAPI获取当前项目的版本号

How do I get the version number of the current project using ToolsAPI in Delphi 10.2

在Delphi 2007我可以使用以下ToolsAPI调用轻松获取当前项目的版本信息:

procedure Test;
var
  ProjectOptions: IOTAProjectOptions;
  Project: IOTAProject;
  Major: Variant;
  Minor: Variant;
  Release: Variant;
  Build: Variant;
begin
  // GxOtaGetCurrentProject is a function in GExpert's GX_OTAUtils unit that returns the current IOTAProject
  Project := GxOtaGetCurrentProject;
  if Assigned(Project) then begin
    ProjectOptions := Project.ProjectOptions;
    if Assigned(ProjectOptions) then begin
      Major := ProjectOptions.Values['MajorVersion'];
      Minor := ProjectOptions.Values['MinorVersion'];
      Release := ProjectOptions.Values['Release'];
      Build := ProjectOptions.Values['Build'];
    end;
  end;
end;

在 Delphi 10.2.3 中,无论实际版本号如何,这将始终 return 版本 1.0.0.0。这是 "simple" 案例:一个 VCL 应用程序。

我还尝试了 "Keys" 值,其中 return 是一个 TStrings 指针。在那里我也得到了 FileVersion 字符串,但它始终是“1.0.0.0”。

我想这与对各种平台和配置的支持有关,但我找不到任何关于它现在应该如何工作的文档。我还在 ToolsAPI.pas 中搜索了 "version" 和 "release",但没有发现任何可疑的东西。

关于如何在 Delphi 10.2 中获取版本信息的任何提示?

版本信息的有效值存储在构建配置平台的单独配置中。要访问配置,首先获取 IOTAProjectOptionsConfigurations 的接口:

cfgOpt := project.ProjectOptions as IOTAProjectOptionsConfigurations;

然后遍历每个 IOTABuildConfiguration:

  for I := 0 to cfgOpt.ConfigurationCount - 1 do
  begin
    cfg := cfgOpt.Configurations[I];
    DoWhatEverWith(cfg);
  end;

请注意每个 IOTABuildConfiguration 可以有多个平台并且 children:

  for S in cfg.Platforms do
  begin
    DoWhatEverWith(cfg.PlatformConfiguration[S]);
  end;

  for I := 0 to cfg.ChildCount - 1 do
  begin
    DoWhatEverWith(cfg.Children[I]);
  end;

根据当前选择的平台和构建配置,可能会使用不同的版本信息值。当前平台和配置可以从 IOTAProject 属性 CurrentPlatformCurrentConfiguration.

阅读 Uwe Raabe 非常有帮助的回答后回答我自己的问题:

获取当前活动配置和平台的版本信息的最简单代码是这样的:

procedure Test;
var
  ProjectOptions: IOTAProjectOptionsConfigurations;
  Project: IOTAProject;
  Major: Variant;
  Minor: Variant;
  Release: Variant;
  Build: Variant;
  cfg: IOTABuildConfiguration;
begin
  // GxOtaGetCurrentProject is a function in GExpert's GX_OTAUtils unit that returns the current IOTAProject
  Project := GxOtaGetCurrentProject;
  if Assigned(Project) then begin
    // as per Uwe's answer
    ProjectOptions := Project.ProjectOptions as IOTAProjectOptionsConfigurations;
    if Assigned(ProjectOptions) then begin
      // this is the currently active configuration
      cfg := ProjectOptions.ActiveConfiguration;
      if Assigned(cfg) then begin
        // Note that the names of the version properties are different!
        Major := cfg.GetValue('VerInfo_MajorVer', True);
        Minor := cfg.GetValue('VerInfo_MinorVer', True);
        Release := cfg.GetValue('VerInfo_Release', True);
        Build := cfg.GetValue('VerInfo_Build', True);
      end;
    end;
  end;
end;

所以这很容易,只要您只需要当前配置的值(在我的情况下,这正是我所需要的)。

  1. 获取当前项目
  2. 获取IOTAProjectOptionsConfigurations接口
  3. 获取当前活动的配置
  4. 使用 GetValue 读取值。请注意版本信息属性的新名称。另请注意,您必须为 IncludeInheritedValues 参数传递 True。

一些注意事项:

  • 您可以使用 GetPropertyCount() 和 GetPropertyName() 枚举可用属性。
  • 除了像上面那样调用 GetValue('name', True),您还可以使用 属性 Value['name']。它会根据需要自动检索递归到祖先配置的结果值。
  • 还有通过 AsInteger 属性 获取类型转换值的选项。同样,这也考虑了祖先配置。请注意,如果类型转换失败,这可能会引发异常。
  • 如果未针对当前配置或任何祖先检查 "Include Version Info" 选项,则 GetValue 会出于任何原因调用 return 版本 1.0.0.0。似乎没有办法检查那个选项,但我这里可能是错的。
  • Embarcadero 可以通过重新路由 ProjectOptions.Values['MajorVersion'] 和对当前配置值的相关调用轻松提供向后兼容性。他们没有,好吧,他们的选择,但在那种情况下,我会期待一些文件。
  • 更改返回到 Delphi XE。