Hi,
I need to update the file and product version numbers of EXEs and DLLs
written in VB6. After doing some research on the net and using some
examples written in C++ I've come up with the code below. When I run
it the return values of the API calls indicate that they succeeded but
the version number of my sample EXE remain unchanged. Can anyone tell
me what I'm doing wrong?
Option Explicit
Private Const RT_VERSION As Long = 16
Private Const LANG_NEUTRAL As Integer = &H0
Private Const LANG_ENGLISH As Long = &H9
Private Declare Function GetFileVersionInfoSize Lib "Version.dll"
Alias "GetFileVersionInfoSizeA" (ByVal lptstrFilename As String,
lpdwHandle As Long) As Long
Private Declare Function GetFileVersionInfo Lib "Version.dll" Alias
"GetFileVersionInfoA" (ByVal lptstrFilename As String, ByVal dwhandle
As Long, ByVal dwlen As Long, lpData As Any) As Long
Private Declare Function BeginUpdateResource Lib "KERNEL32" Alias
"BeginUpdateResourceA" (ByVal pFileName As String, ByVal
bDeleteExistingResources As Long) As Long
Private Declare Function UpdateResource Lib "KERNEL32" Alias
"UpdateResourceA" (ByVal hUpdate As Long, ByVal lpType As Long, ByVal
lpName As Long, ByVal wLanguage As Long, lpData() As Byte, ByVal
cbData As Long) As Long
Private Declare Function EndUpdateResource Lib "KERNEL32" Alias
"EndUpdateResourceA" (ByVal hUpdate As Long, ByVal fDiscard As Long)
As Long
Private Sub UpdateFileVersion(ByVal vstrFilePath As String)
Dim llngHandle As Long
Dim llngVersionInfoLength As Long
Dim llngResult As Long
Dim lbytBuffer() As Byte
Dim llngResourceHandle As Long
Dim llngReturnValue As Long
llngVersionInfoLength = GetFileVersionInfoSize(vstrFilePath,
llngHandle)
If llngVersionInfoLength <> 0 Then
ReDim lbytBuffer(llngVersionInfoLength - 1)
llngResult = GetFileVersionInfo(vstrFilePath, 0,
llngVersionInfoLength, lbytBuffer(0))
If llngResult <> 0 Then
'QUICK AND DIRTY UPDATING OF VERSION NUMBER, JUST TO CHECK
IT WORKS
'UPDATE FILE VERSION NUMBER
lbytBuffer(50) = 5
lbytBuffer(48) = 6
lbytBuffer(54) = 7
lbytBuffer(52) = 8
'UPDATE PRODUCT VERSION NUMBER
lbytBuffer(58) = 5
lbytBuffer(56) = 6
lbytBuffer(62) = 7
lbytBuffer(60) = 8
llngResourceHandle = BeginUpdateResource(vstrFilePath, 0)
If llngResourceHandle <> 0 Then
llngReturnValue = UpdateResource(llngResourceHandle,
RT_VERSION, 1, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lbytBuffer,
llngVersionInfoLength)
If llngReturnValue = 0 Then
MsgBox "Unable to update resource (" &
Err.LastDllError & ")", vbExclamation, Me.Caption
End If
llngReturnValue =
EndUpdateResource(llngResourceHandle, 0)
If llngReturnValue <> 0 Then
MsgBox "Version number updated", vbInformation,
Me.Caption
Else
MsgBox "Unable to write updated resource (" &
Err.LastDllError & ")", vbExclamation, Me.Caption
End If
Else
MsgBox "Unable to retrieve resource update handle",
vbExclamation, Me.Caption
End If
Else
MsgBox "Unable to get file version info (" &
Err.LastDllError & ")", vbExclamation, Me.Caption
End If
Else
MsgBox "Unable to get file version info size (" &
Err.LastDllError & ")", vbExclamation, Me.Caption
End If
End Sub
Public Function MAKELANGID(ByVal vintPrimaryLanguage As Integer, ByVal
vintSubLanguage As Integer) As Long
MAKELANGID = (vintSubLanguage * 1024) Or vintPrimaryLanguage
End Function
As it says in the comments I intend to find a more elegant way of
setting the version numbers themselves but I'm just using a quick and
dirty method for now to check it works.
Thanks in advance,
Colin
Thorsten Albers - 04 Jul 2008 01:47 GMT
google@colinbaker.me.uk schrieb im Beitrag
<6b62448a-eb65-4e59-8ed9-90a502813812@j22g2000hsf.googlegroups.com>...
> ReDim lbytBuffer(llngVersionInfoLength - 1)
> llngResult = GetFileVersionInfo(vstrFilePath, 0,
> llngVersionInfoLength, lbytBuffer(0))
This is nonsense! For 'lbytBuffer()' 'llngVersionInfoLength - 1' is
allocated, and then GetFileVersionInfo() is told that 'lbytBuffer()' has
'llngVersionInfoLength' bytes. The '- 1' makes sense only if used as
follows:
ReDim lbytBuffer(0 To llngVersionInfoLength - 1)
> 'UPDATE FILE VERSION NUMBER
> lbytBuffer(50) = 5
[quoted text clipped - 7 lines]
> lbytBuffer(62) = 7
> lbytBuffer(60) = 8
The VS_FIXEDFILEINFO structure of the VS_VERSION_INFO resource data starts
at offset +40 (+28h); the file version is stored in the 3rd >>and 4th<<
DWORD of the structure (8, not 4 bytes!) and therefore starts at offset +48
(+30h); the same is valid for the product version which starts at offset
+56 (+38h).
> If llngResourceHandle <> 0 Then
> llngReturnValue = UpdateResource(llngResourceHandle,
> RT_VERSION, 1, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lbytBuffer,
> llngVersionInfoLength)
AFAIK UpdateResource() doesn't search for an appropriate resource but uses
exactly the given one. Are you really sure that the version info resource
has the 'neutral language'? Usually it has the english language, or it may
have been localized for another specific language other than 'neutral'.

Signature
----------------------------------------------------------------------
Thorsten Albers albers(a)uni-freiburg.de
----------------------------------------------------------------------
google@colinbaker.me.uk - 04 Jul 2008 09:17 GMT
Thanks for your reply Thorsten.
When declaring an array in VB6 the number indicates the upper bound of
the array not the number of items in the array like most other
languages. Since VB6 defaults to a lower bound of 0 this is in fact a
correct declaration (not nonsense!).
If you look carefully where I'm updating the file and product numbers
you'll see that I am using offsets of 48 and 56 repectively, I've just
placed them in order of Major, Minor, Build and Revision instead of
the order they appear in the data.
I'm not sure about the language, some examples I've found use language
neutral and others US English.
Colin
Thorsten Albers - 04 Jul 2008 12:28 GMT
google@colinbaker.me.uk schrieb im Beitrag
<f6edc302-9add-4079-8790-8318ab3ceded@x35g2000hsb.googlegroups.com>...
> When declaring an array in VB6 the number indicates the upper bound of
> the array not the number of items in the array like most other
> languages. Since VB6 defaults to a lower bound of 0 this is in fact a
> correct declaration (not nonsense!).
Sorry, that was my fault caused by the fact that currently I am working
with C more often than with VB.
> If you look carefully where I'm updating the file and product numbers
> you'll see that I am using offsets of 48 and 56 repectively, I've just
> placed them in order of Major, Minor, Build and Revision instead of
> the order they appear in the data.
Sorry, again my fault. In each case I have looked only at the first line
following the comment...
> I'm not sure about the language, some examples I've found use language
> neutral and others US English.
Get yourself a good resource viewer/editor, open the executable, and check
the version info resource. A good one IMHO is Resource Hacker written by
Angus Johnson from
http://www.angusj.com/resourcehacker/
In addition: In another newsgroup there were reported problems with
UpdateResource() on MS Windows Vista...

Signature
----------------------------------------------------------------------
Thorsten Albers albers(a)uni-freiburg.de
----------------------------------------------------------------------