问题
In Delphi 2007 I can easily get the version information of the current project using the following ToolsAPI calls:
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;
In Delphi 10.2.3 this will always return the version 1.0.0.0 regardless of the actual version number. This is the "simple" case: A VCL application.
I also tried the "Keys" value which returns a TStrings pointer. There I also get the FileVersion string, but it is always "1.0.0.0".
I guess this has something to do with the support for various platforms and configurations, but I could not find any documentation, on how it should work now. I also searched the ToolsAPI.pas for "version" and "release", but nothing suspicious showed up.
Any hints on how I can get the version information in Delphi 10.2?
回答1:
The effective values for version info are stored in separate configurations for build configuration and platform. To get access to the configurations, first get an interface to IOTAProjectOptionsConfigurations:
cfgOpt := project.ProjectOptions as IOTAProjectOptionsConfigurations;
Then iterate over each IOTABuildConfiguration:
for I := 0 to cfgOpt.ConfigurationCount - 1 do
begin
cfg := cfgOpt.Configurations[I];
DoWhatEverWith(cfg);
end;
Be aware that each IOTABuildConfiguration can have several platforms and 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;
Depending on which platform and build configuration is currently selected, different values for version info may be used. The current platform and configuration can be retrieved from the IOTAProject properties CurrentPlatform and CurrentConfiguration.
回答2:
To answer my own question after reading Uwe Raabe's very helpful answer:
The simplest code for getting the version information of the currently active configuration and platform is this:
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;
So it is quite easy as long as you only want the values from the current configuration (which in my case is exactly what I need).
- Get the current project
- Get the IOTAProjectOptionsConfigurations interface
- Get the currently active configuration
- Read the values using GetValue. Note the new names for the version info properties. Also note, that you must pass True for the IncludeInheritedValues parameter.
Some notes:
- You can enumerate the available properties with GetPropertyCount() and GetPropertyName().
- Instead of calling GetValue('name', True) as above, you can also use the property Value['name']. It automatically retrieves the resulting value recursing to ancestor configurations as necessary.
- There is also the option to get type casted values via the AsInteger property. Again this also takes ancestor configurations into account. Note that this might raise exceptions if the type conversion fails.
- If the "Include Version Info" option is not checked for the current configuration or any of the ancestors, the GetValue calls return version 1.0.0.0 for whatever reason. There seems to be no way to check for that option, but I may be wrong here.
- Embarcadero could have easily provided backwards compatibility by rerouting the ProjectOptions.Values['MajorVersion'] and related calls to the values of the current configuration. They didn't, OK, their choice, but in that case I would have expected some documentation.
- The change goes back to Delphi XE.
来源:https://stackoverflow.com/questions/51180066/how-do-i-get-the-version-number-of-the-current-project-using-toolsapi-in-delphi