If you’ve ever looking closely at Windows applications, you know that Windows Version Numbers are composed of 4 parts:
- Major version
- Minor version number
- Revision number
- Build number
So a version of 4.8.3.9888 would typically mean Major version 4, Minor version 8, Revision 3, Build 9888.
If you’ve ever looked at VB’s Project properties box, though, you’ve probably noticed the disconnect.
Obviously, VB directly supports the Major and Minor, and appearently, the Revision number.
But, build a VB6 app with unique values in for each number and then view the app’s properties via Windows Explorer:
In this particular app’s case, Major and Minor are 0, and Revision was set to 49. However, according to the Windows Property panel, the Build number is 49. VB internally makes the Build number what you enter as the Revision number in the VB project property UI.
Now, whether this was just a typo on the part of the VB developers or an intentional “feature”, I can’t say. But it definitely can cause confusion and make it difficult to identify versions of your app out in the field. Then there’s the constant explaining of why your app’s revision always seems to be 0, but other applications have something there.
In a previous post on VB and resources, I mention the Microsoft Resource Compiler, a utility that can compile resource files into RES files, which can then be compiled into your application by VB.
This combination works wonders if all you want to do is embed icons, bitmaps, strings or arbitrary files into the resources of your app.
And, if you look at the RC documentation, you’d see info on VERSIONINFO statement that is used to define a Version Info Resource.
So, it would stand to reason that if you created a resource file, say like this:
VersionInfoTest.rc
1 VERSIONINFO FILEVERSION 1,2,3,4 PRODUCTVERSION 1,2,3,4 FILEOS 0x4 FILETYPE 0x1 //// 2 for dll, 1 for exe { BLOCK "StringFileInfo" { BLOCK "000004b0" { VALUE "CompanyName", "MyCompany" VALUE "ProductName", "MyProduct" VALUE "FileDescription", "MyFileDesc" VALUE "LegalCopyright", "MyLegalCopyright" VALUE "LegalTrademarks", "MyLegalTrademark" VALUE "OriginalFilename", "MyOriginalFilename" VALUE "ProductVersion", "1.2.3.4" VALUE "FileVersion", "1.2.3.4" VALUE "Comments", "MyComments" VALUE "InternalName", "MyInternalName" } } BLOCK "VarFileInfo" { VALUE "Translation", 0x0000 0x04B0 } }
Then, all you should have to do is compile the RC file with RC.EXE, load up VB, add the resulting RES file to your project and you’d be done.
Unfortunately, the path to enlightnment is never straightforward, and neither is the process of getting a proper version number into a VB6 executable.
The problem is that VB post-processes the compiled executable in order to put the version information from the Project properties screen into the VERSIONINFO resource. This means that the nice, correct VERSIONINFO resource that you just compiled into the executable get’s stomped on by whatever you happen to have in the Project Properties dialog, and that dialog will always reset the Windows Revision number to 0, and use the VB Revision number as the Windows Build number.
What you have to do is post-post-process your exe and put the correct VERSIONINFO resource back in after VB is completely finished with the file.
And the easiest way to do that is with a handy free utility called Resource Hacker. This utility allows you to easily open, view, and even extract all the resources in any EXE or DLL. If you want to just pull all the icons out of a file’s resources, there are definitely better ways. But if you really want to poke around the resources in a file, ResHacker is perfect. Plus, it’s got a very handy, if not a little arcane, command line interface that will allow you to automate much of the process via MAKE files or batch scripts.
Make sure the RESHACKER.EXE is on your path, then run:
reshacker -addoverwrite "yourexe.exe", "yourexe.exe", "yourexe-VersionInfo.res", versioninfo, 1 , 1033
I’m assuming your compiled application is called yourexe.exe, and that you’ve compiled an RC file with a VERSIONINFO resource in it to the file yourexe-VersionInfo.res.
Resource hacker will dutifully wipe out the VB created VERSIONINFO resource and replace it with the one compiled from your RC script.
One important note, though. ResHacker will not merge a single resource, and all of the version information is considered a single resource. That means that you need to specify all the pertinent version info properties in your RC file, because everything specified via the VB Project Properties dialog will get replaced.
“But”, you say, “the version numbers themselves appear to be replicated 4 times in the RC file! I’m a lazy programmer and the thought of updating 4 copies of the version number just seems, well, wrong.”
And you’d be right.
Fortunately, there is a way to convince RC.EXE to allow you to specify the version number for your app only once. However, doing so is, like the concept of using resources in a VB app, more complicated that you would at first imagine.
I’ll discuss that in my next post.