How to cope with version info? By , journalist and programmer For you as a programmer it is essential to add useful product and version information to your applications and DLL's. This is really not difficult, but there are certain rules to follow in order to make the info accessible for your fellow programmers. Or for yourself, if you want to use portions of it in your application's About Box. Those rules were set by Microsoft Corporation, I assume. After all 'they' were the inventors of the Windows API. In this perspective it is much interesting to see that Microsoft-programmers sometimes don't obey their own rules. In this article I'm going to discuss 2 aspects of the version info issue: These points apply, as you will understand, to our programming skills. To see which information I'm talking about, simply right-click on an application's name in any folder of Windows Explorer, select Properties and open the Version-tab (if present). This is - approximately - what you'll get: |
|
![]() |
As you may have noticed, this screenshot shows Microsoft Word's Version-tab. Why this one? It proves that within my copy of Word97 relevant version information surely has been included. Nevertheless I cannot retrieve this same info using the relevant Windows API-calls. Following the rules as explained in a Microsoft-support article my reward was just an empty Message Box. |
Resource definition file Before I come to explain how Microsoft coders put this kind of 'bugs' in some of their applications, I'm going to discuss how to write version info in a Resource Definition File. This is the file that programmers always use to include icons and so on within their applications and that has to be compiled using Microsoft's RC.EXE and Power Basic's PBRES.EXE. This is an example: #include "D:\PBWIN70\WINAPI\RESOURCE.H" VS_VERSION_INFO VERSIONINFO // numeric or .... FILEVERSION 1, 1, 0, 0 // binary version .... PRODUCTVERSION 1, 0, 0, 0 // and product info FILEOS VOS_WINDOWS32 // platform = 32 bits Windows FILETYPE VFT_APP // application (use VFT_DLL for DLL) BEGIN BLOCK "StringFileInfo" // this is the info we're talking about BEGIN BLOCK "041304E4" // &H0413 = LANG_ID Dutch, &H04E4 = charset ANSI BEGIN VALUE "CompanyName", "Egbert Zijlema\0" VALUE "FileDescription", "Application to test version resource file\0" VALUE "FileVersion", "1.01\0" VALUE "InternalName", "GetVer for Windows\0" VALUE "LegalCopyright", "Copyright \251 2000: Egbert Zijlema\0" VALUE "LegalTradeMarks", "Don't have such, legal nor illegal\0" VALUE "OriginalFilename", "GETVER.EXE\0" VALUE "ProductName", "GetVer\0" VALUE "ProductVersion", "1\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x413, 1252 // tell application it's Dutch + ANSI END ENDThe part discussed in this article is StringFileInfo. There you can store pre-defined items, such as "CompanyName", "FileVersion" etc. According to Microsoft's WIN32.HLP there are 8 pre-defined items:
Note that some applications have a Comment item included in the list. Not very smart, because Windows is sorting the items alphabetically. So 'comment' will come first and, as a result, will be visible when the user opens the Version-tab of your application. Let "CompanyName" be the first item, until you believe that your comments are more important than your business.VarFileInfo performs two tasks: 1. it adds the language item to the list under Version-tab 2. it tells your application how to identify the information in order to retrieve it properly Possibly there is a third task? Anyhow, something does not happen when you don't include "VarFileInfo\Translation" in your resource definition file: the first item of the list ("CompanyName") will not automatically be selected and opened when clicking the Version-tab.Don't miss this: the 2 values in "VarFileInfo\Translation" must be exactly the same as the hexadecimal string in "StringFileInfo". This 8-digit string is actually a combination of two 4-digit strings, representing a language identifier and a character set. It is at least somewhat confusing that those values are written so differently. 0413 is a normal hexadecimal string, 0x413 is the way to write an hexadecimal value in a resource definition file. 04E4 is the hexadecimal representation of 1252, which appears to be a decimal number. In this example 0413 and 0x413 are the language identifier for Dutch, 04E4 and 1252 both represent the ANSI character set. Valid language and charset identifiers can be found in the WIN32.HLP file. Which language identifier you want to use is up to you. But it is a bit odd to present Hebrew or Russian under the Properties Version-tab while your application's screen output is Aussie-English, don't you agree? How to retrieve it FUNCTION FileVersion(app$) AS STRING LOCAL nSize AS LONG, ret AS LONG, dummy AS LONG LOCAL buff AS STRING, LangID AS STRING, CharsetID AS STRING, temp AS STRING LOCAL szPathName AS ASCIIZ * %MAX_PATH, svPtr AS ASCIIZ PTR, LangPtr AS LONG PTR ' skipped ' skipped ' skipped ' get language information and convert it (via two 4-digit hex strings) to a string ' example: "040904E4" ret = VerQueryValue(BYVAL STRPTR(buff), "\VarFileInfo\Translation", LangPtr, nSize) LangID = HEX$(LOWRD(@LangPtr), 4) CharsetID = HEX$(HIWRD(@LangPtr), 4) block$ = "\StringFileInfo\" + LangID + CharsetID ' finally get the information about the product VerQueryValue BYVAL STRPTR(buff), block$ + "\InternalName", svPtr, nSize temp = temp + @scPtr + $CRLF ' store result in a temp-var ' repeat VerQueryValue for additional string values FUNCTION = temp END FUNCTIONVerQueryValue is the most important of the 3 API-calls involved. It tries to get the language and charset information first. The values found should be converted to their 4-digit hex-representations and then combined to one 8-character hex string. Then the same FUNCTION must be called as often as the number of pre-defined strings your application should find. During these repetetive calls it uses the found hex string as 'location'. It's clear what will happen when the converted hex string does not match the one in StringFileInfo: no information can be obtained. And this is what Microsoft coders obviously did wrong in WINWORD.EXE and other applications. They passed language identifier 0x000 (= Neutral Language) + charset 1252 (= ANSI) through VarFileInfo\Translation, but used lang-charset identifier "040904E4" (= American English + ANSI) in StringFileInfo. |
|
Where to download? |