Version Build

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

An automated method to generate meaningful version numbers in a MS Devstudio project’s
version resources has been a surprisingly popular topic. After following leads to a
variety of solutions, none that I came across quite do what I would like. Here is a
solution that suits my needs, perhaps it will suit yours too.

The resource version number is a structure of two double word values, the Most
Significant Value (MSV) and the Least Significant Value (LSV). Each value is broken into
two parts, the high word and the low word. In a resource script, this is represented by
something like "FILEVERSION 1,0,0,1" or "PRODUCTVERSION 1,0,0,1".
  The "1,0" is the high word/low word of the MSV. The "0,1" is
the high word/low word of the LSV. There is also a string representation of the versions
in the StringFileInfo block.

I find it desirable to to use the LSV to track incremental builds. Generally, marketing
types like to dictate the MSV. So while I may be working on what I consider a Beta
release, they want it stamped as version 2.1. But I digress…. 🙂

The protocol I use for development versioning is to set the high word of the LSV to a
value that indicates the year and day of the build. The low word counts the builds in the
given day.

The way the high word is formulated is this: Using the ASCII decimal representation of
the year, take the first digit ( e.g, 1998=1, 1999=1, 2000=2 ), multiply times 10, then
add the last digit of the year (e.g., 1998=8, 1999=9, 2000=0), then multiply the sum by
1000 (e.g., 1998=18000, 1999=19000, 2000=20000). Now add the day of the year (e.g., Jan 1=
1, Jan 31=31, Feb 1=32). The high word for February 1, 1999 would therefore be 19032, the
high word for December 25, 1998 would be 18356, while the high word for June 23, 2000
would be 20175.

The low word is started at 1 for the first build of the day, and incremented by 1 for
each ensuing build.

Armed with this information, it is possible to go back in the source control
application and find the version of the source that generated any given build. But of
course it is tedious and demands more diligence than I can muster to reliably maintain the
version by manual input. Thus I present this Devstudio macro that does all this for me,
"VersionBuild".

When invoked, VersionBuild will attempt to locate the version resource. If successful,
it will modify the FILEVERSION entry according to the protocol outlined above. If
successful, VersionBuild will continue to build the project currently active.

By default, VersionBuild will synchronize the LSV of the PRODUCTVERSION as well as the
StringFileInfo block’s FileVersion and ProductVersion. There are two variables at the top
of the macro, bPRODUCTVERSION and bStringFileInfo, which may be set appropriately to
control which version types you want modified.



Sub VersionBuild()
'DESCRIPTION: Sets LSV of version number: Hi word = 1st digit of year + last digit of year + day of year; Lo word = 1 if new Hi word or previous + 1 if same Hi word
'Patrick Dell'Era
'[email protected]
'
    Dim i
    Dim strHiWord
    Dim strLoWord
    Dim nHiWord, nOldHiWord
    Dim LSV
    Dim strTemp
    Dim strMsg
    Dim bPRODUCTVERSION, bStringFileInfo

    ' Set to True if you want the PRODUCTVERSION synchronized
    bPRODUCTVERSION = True
    ' Set to True if you want the StringFileInfo block synchronized
    bStringFileInfo = True

    strMsg = "There was a problem modifying your version resource. Could not locate "

    ' Open the resource file as text
    ' NOTE: You will probably be informed that the resource is
    ' already opened in the resource editor. You'll need to confirm
    ' that you want to close that and open the file as text. Otherwise,
    ' we will return an error informing you that the resource file is
    ' not in the documents collection

    ' Trap errors for likely suspects
    On Error Resume Next
    ' Attempt to open the document
    Documents.Open (ActiveProject.Name + ".rc"), "Text"
    If Err.Number <> 0 Then
        MsgBox ("Error 0x" & Hex(Err.Number) & ":  " & Err.Description)
        Exit Sub
    End If
    ' Try to bring it to the fore
    Windows(ActiveProject.Name + ".rc").Active = True
    If Err.Number <> 0 Then
        MsgBox ("Error 0x" & Hex(Err.Number) & ":  " & Err.Description)
        Exit Sub
    End If
    ' Seek out the version resource block
    If ActiveDocument.Selection.FindText("VS_VERSION_INFO VERSIONINFO", dsMatchWord + dsMatchCase) = False Then
        MsgBox strMsg + """VS_VERSION_INFO VERSIONINFO"""
        Exit Sub
    End If
    ' Seek the binary FILEVERSION entry
    If ActiveDocument.Selection.FindText("FILEVERSION", dsMatchWord + dsMatchCase) = False Then
        MsgBox strMsg + """FILEVERSION"""
        Exit Sub
    End If
    ' Skip first two entries for the MSV portion of the version
    For i = 1 To 2
        If ActiveDocument.Selection.FindText(",") = False Then
            MsgBox strMsg + "comma #" + Trim(CStr(i)) + " in ""FILEVERSION""."
            Exit Sub
        End If
    Next
    ' Move off comma
    ActiveDocument.Selection.CharRight
    ' Select the entire number
    ActiveDocument.Selection.WordRight dsExtend
    ' Copy the number string
    strTemp = ActiveDocument.Selection.Text
    ' Convert the number string into an integer
    nOldHiWord = CInt(strTemp)
    ' Get the current year as a string
    strTemp = CStr(DatePart("yyyy", Now))
    ' Make the high word of the LSV equal to the first digit
    ' of the year ( 1998 = 1; 1999 = 1; 2000 = 2 ...) and
    ' the last digit of the year ( 1998 = 8; 1999 = 9; 2000 = 0 ...)
    strHiWord = CStr(Left(strTemp, 1)) + CStr(Right(strTemp, 1))
    ' Convert the string into an integer value times 1000 to allow
    ' room for the day of the year value that is calculated next
    nHiWord = CInt(strHiWord) * 1000
    ' Find out the day of the year for today
    LSV = CInt(DatePart("y", Now))
    ' Add it to the previously calculated year-based value
    nHiWord = nHiWord + LSV
    ' Preserve a copy of the value as a string
    strHiWord = CStr(nHiWord)

    ' If the current value of the high word of the LSV is not the
    ' same as the newly calculated one, then replace the old with
    ' the new
    If nHiWord <> nOldHiWord Then   ' new day
        strHiWord = CStr(nHiWord)
        ActiveDocument.Selection = strHiWord
    End If
    ' Let's find the low word of least significant value and adjust it
    If ActiveDocument.Selection.FindText(",") = False Then
        MsgBox strMsg + "comma #3" + " in ""FILEVERSION""."
        Exit Sub
    End If
    ' Move off the comma
    ActiveDocument.Selection.CharRight
    ' Select the entire number
    ActiveDocument.Selection.WordRight dsExtend
    ' If the high word of the LSV has changed, then we have begun a
    ' new day of compilation fun. So reset the low word to 1
    If nHiWord <> nOldHiWord Then   ' new day, restart counter
        LSV = 1
    Else
        ' Same day, new compilation, so increment the low word of
        ' the LSV
        ' Grab the number into a text string
        strTemp = ActiveDocument.Selection.Text
        ' Convert it into an integer
        LSV = CInt(strTemp)
        ' Increment the integer
        LSV = LSV + 1
    End If
    ' Convert the low word of the LSV into a string
    strLoWord = CStr(LSV)
    ' Copy the string into the selected text
    ActiveDocument.Selection = strLoWord

    ' NOTE: The following code will synchronize the PRODUCTVERSION, FileVersion, and ProductVersion
    ' entries of the resource file with the FILEVERSION. This is done with the same techniques.
    ' Set the bPRODUCTVERSION and bStringFileInfo values at the top of the macro appropriately.

    If bPRODUCTVERSION Then
        ' Now seek out PRODUCTVERSION and synchronize
        If ActiveDocument.Selection.FindText("PRODUCTVERSION", dsMatchWord + dsMatchCase) = False Then
            MsgBox strMsg + """PRODUCTVERSION"""
            Exit Sub
        End If
        For i = 1 To 2
            If ActiveDocument.Selection.FindText(",") = False Then
                MsgBox strMsg + "comma #" + Trim(CStr(i)) + " in ""PRODUCTVERSION""."
                Exit Sub
            End If
        Next
        ActiveDocument.Selection.CharRight
        ActiveDocument.Selection.WordRight dsExtend
        ActiveDocument.Selection = strHiWord
        If ActiveDocument.Selection.FindText(",") = False Then
            MsgBox strMsg + "comma #3" + " in ""PRODUCTVERSION""."
            Exit Sub
        End If
        ActiveDocument.Selection.CharRight
        ActiveDocument.Selection.WordRight dsExtend
        ActiveDocument.Selection = strLoWord
    End If

    If bStringFileInfo Then
        ' Now seek out FileVersion in the string block and synchronize
        If ActiveDocument.Selection.FindText("FileVersion", dsMatchWord + dsMatchCase) = False Then
            MsgBox strMsg + """FileVersion"""
            Exit Sub
        End If
        For i = 1 To 3
            If ActiveDocument.Selection.FindText(",") = False Then
                MsgBox strMsg + "comma #" + Trim(CStr(i)) + " in ""PRODUCTVERSION""."
                Exit Sub
            End If
        Next
        ActiveDocument.Selection.WordRight
        ActiveDocument.Selection.WordRight dsExtend
        ActiveDocument.Selection = strHiWord
        If ActiveDocument.Selection.FindText(",") = False Then
            MsgBox strMsg + "comma #4" + " in ""PRODUCTVERSION""."
            Exit Sub
        End If
        ActiveDocument.Selection.WordRight
        ActiveDocument.Selection.WordRight dsExtend
        ActiveDocument.Selection = strLoWord

        If bPRODUCTVERSION Then
            ' Now seek out ProductVersion in the string block and synchronize
            If ActiveDocument.Selection.FindText("ProductVersion", dsMatchWord + dsMatchCase) = False Then
                MsgBox strMsg + """ProductVersion"""
                Exit Sub
            End If
            For i = 1 To 3
                If ActiveDocument.Selection.FindText(",") = False Then
                    MsgBox strMsg + "comma #" + Trim(CStr(i)) + " in ""ProductVersion""."
                    Exit Sub
                End If
            Next
            ActiveDocument.Selection.WordRight
            ActiveDocument.Selection.WordRight dsExtend
            ActiveDocument.Selection = strHiWord
            If ActiveDocument.Selection.FindText(",") = False Then
                MsgBox strMsg + "comma #4" + " in ""ProductVersion""."
                Exit Sub
            End If
            ActiveDocument.Selection.WordRight
            ActiveDocument.Selection.WordRight dsExtend
            ActiveDocument.Selection = strLoWord
        End If  ' bPRODUCTVERSION
    End If ' bStringFileInfo

    'close RC file
    ActiveDocument.Close
    If Err.Number <> 0 Then
        MsgBox ("Error 0x" & Hex(Err.Number) & ":  " & Err.Description)
        Exit Sub
    End If
    'build active project
    ExecuteCommand "BuildToggleBuild"

End Sub




More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read