VSoft Technologies Blogs

rss

VSoft Technologies Blogs - posts about our products and software development.

In this post, we'll take a look at the various options for managing and updating Version Info in Delphi projects using FinalBuilder.

Windows Version Info Primer

Windows Version Info (ie the version info shown in explorer) is stored in a VERSIONINFO resource inside the executable (exe or dll). These resources are created by defining a .rc file, and compiling with either the windows resource compiler (rc.exe) or Delphi's provided resource compiler (brcc32 or cgrc depending on the delphi version). This results in a .res file, which can be linked into exe at compile time by referencing it in the source code, e.g :

{$R 'myresource.res'}

I highly recommend familiarising yourself with the VERSIONINFO resource type and it's parts.

Delphi IDE Support for Version Info

The Delphi IDE creates a [YourProjectName].res file next to the dpr or dpk when you create a new project. This is where the IDE will place the VERSIONINFO resource when you enable the option to "Include version information in project".  When you compile the project in the IDE, if needed the IDE will regenerate this res file with updated version info before it is linked into the executable.  For exe's, this resource file also includes the MAINICON resource (the icon shown in explorer).

You do not have to use this feature, you can leave the option turned off and manage the version info yourself, by creating your own resource script (.rc) with a VERSIONINFO structure,  and compiling it and referencing the resulting .res file in your source code. You can even just reference the .rc file

{$R 'myresource.res' 'myresource.rc'}

and the IDE will compile the rc file and link in the resulting res file. The caveat to this technique is that the command line compiler (dcc32, dcc64 etc) does not support this. 

If your binary doesn't have version info, or has incorrect version info, it's typically because :

1) The version info  resource wasn't referenced in the source and wasn't linked in
2) There are duplicate VERSIONINFO resources linked, windows will pick the first one it finds.
3) You set the version info on the wrong IDE configuration (more on this below). 

The Delphi IDE, along with the dproj file (which is an msbuild project file), uses a convoluted configuration inheritance mechanism to set project properties, including version info. Many a developer has been caught out by this scheme, setting the version info at the wrong node in the heirachy, resulting in no version info in their executables. There have also been issues with dproj files that have been upgraded through multiple versions of delphi over the years.

Using FinalBuilder

In the development environment, the version info usually doesn't matter too much, but for formal releases it's critical, so it's best to leave setting/updating your version info  to your automated build tool or your continuous integration server. In FinalBuilder we have invested a lot of time and energy to making version info work correctly with all the different versions of delphi, dealing with the vagaries and subtle differences with each version (and there are many!).

On the Delphi action in FinalBuilder, the Version Info tab presents the version info in a similar way to old versions of delphi IDE did (a much nice ui that the current version imho). This ui allows you control all the various version info properties (and there are a lot!). Note that these will only take effect if you have the "Regenerate resource" option checked on the Project tab (ie, regenerate yourproject.res). 

Note that the Major, Minor, Release and Build fields are number spin edits, and cannot take FinalBuilder variables. That can easily be worked around with some simple scripting, in the BeforeAction script event  (javascript):

Another option is to use Property Sets to provide the source of the Version Info. Property sets are especially useful when you have multiple actions that need the same version info, or at least to share the same version numbers. Creating a Property Set is trivial, just drop a PropertySet Define action on your target, before the Delphi Action. In the PropertySet Define action, select Win32 Version Info to manage all version info properties, or Win32 Version Numbers to have the property set just manage the major, minor, release and build numbers.

To set the property set values, add a PropertySet Assign Values action before the Delphi action.

Then in the Delphi action it's a simple task to select the property set in the version info tab

Notice that the version number fields are disabled, since they are now provided by the property set. If you choose the Win32 Version Info property set type, more fields are disabled.

One last thing I should mention, is that along with the Version Info and the MAINICON, the project.res file also typically (well for windows at least) contains the manifest file. I recommend you look at the Resource Compiler tab, where it lets you choose which resource compiler to use (more useful in older versions of delphi, where brcc32 didn't cope with some hicolor icon types) and specify the manifest file. I discussed windows manifest files a few years ago in this blog post.

Showing 1 Comment

Avatar
Tim 6 years ago

A very useful summary, and we have used this method, with a property set maintained/updated in FB, for many years. However this only manages (very reliably) the production version number. I have not yet found a bulletproof way of updating the version number for debug builds at the same time, in FB while it is building the release version. In consequence I too often build one DLL in the IDE to investigate something in our current release, and discover that the DLL debug version resource is a couple of build numbers different, or sometimes 1.0, or absent entirely. Since most of our apps check for a matching DLL version, the result is usually a failure to start the app followed by some swearing and an IDE rebuild of the DLL. I once wrote a utility that fixed this, and had FB run it after each production compile, but it only lasted a short while until the next Delphi release (of course) broke it. If there is a way to do this, it would be great if you could update your blog to cover this.



Comments are closed.