Как получить номер версии текущего проекта, используя ToolsAPI в 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 это всегда будет возвращать версию 1.0.0.0 независимо от фактического номера версии. Это "простой" случай: приложение VCL.

Я также попробовал значение "Keys", которое возвращает указатель TStrings. Там я также получаю строку FileVersion, но это всегда "1.0.0.0".

Я думаю, это как-то связано с поддержкой различных платформ и конфигураций, но я не смог найти никакой документации о том, как это должно работать сейчас. Я также искал в ToolsAPI.pas "версию" и "выпуск", но ничего подозрительного не обнаружилось.

Любые советы о том, как я могу получить информацию о версии в Delphi 10.2?

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 может иметь несколько платформ и дочерних элементов:

  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 CurrentPlatform и CurrentConfiguration.

Чтобы ответить на мой собственный вопрос после прочтения очень полезного ответа Уве Раабе:

Простейший код для получения информации о версии текущей активной конфигурации и платформы:

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. Обратите внимание на новые имена для свойств информации о версии. Также обратите внимание, что вы должны передать True для параметра IncludeInheritedValues.

Некоторые заметки:

  • Вы можете перечислить доступные свойства с помощью GetPropertyCount() и GetPropertyName().
  • Вместо вызова GetValue('name', True), как указано выше, вы также можете использовать свойство Value['name']. Он автоматически извлекает результирующее значение, возвращающееся в конфигурации предков по мере необходимости.
  • Существует также возможность получить приведенные значения типа через свойство AsInteger. Опять же, это также принимает во внимание конфигурации предков. Обратите внимание, что это может вызвать исключения в случае сбоя преобразования типа.
  • Если опция "Включить информацию о версии" не проверена для текущей конфигурации или какого-либо из предков, вызовы GetValue возвращают версию 1.0.0.0 по любой причине. Кажется, нет никакой возможности проверить этот вариант, но я могу ошибаться здесь.
  • Embarcadero мог бы легко обеспечить обратную совместимость, перенаправив ProjectOptions.Values ​​['MajorVersion'] и связав вызовы со значениями текущей конфигурации. Конечно, они не сделали своего выбора, но в этом случае я бы ожидал некоторую документацию.
  • Изменение восходит к Delphi XE.
Другие вопросы по тегам