1+ Imports System.IO
2+ Imports System.Runtime.InteropServices
3+ Imports Microsoft.SmallVisualBasic
4+
5+ Public Class NativeResourceUpdater
6+
7+ <DllImport( "kernel32.dll" , SetLastError:= True , CharSet:=CharSet.Auto)>
8+ Public Shared Function BeginUpdateResource(fileName As String , bDeleteExistingResources As Boolean ) As IntPtr
9+ End Function
10+
11+ <DllImport( "kernel32.dll" , SetLastError:= True , CharSet:=CharSet.Auto)>
12+ Public Shared Function UpdateResource(hUpdate As IntPtr, lpType As IntPtr, lpName As IntPtr, wLanguage As UShort, lpData As Byte (), cbData As UInteger) As Boolean
13+ End Function
14+
15+ <DllImport( "kernel32.dll" , SetLastError:= True , CharSet:=CharSet.Auto)>
16+ Public Shared Function EndUpdateResource(hUpdate As IntPtr, fDiscard As Boolean ) As Boolean
17+ End Function
18+
19+ Public Shared Sub UpdateVersionResource(exePath As String , info As ProgramInfo)
20+ Dim hUpdate = BeginUpdateResource(exePath, False )
21+ If hUpdate = IntPtr.Zero Then
22+ Throw New System.ComponentModel.Win32Exception()
23+ End If
24+
25+ Dim versionResource = BuildVersionResource(info)
26+ ' RT_VERSION is resource type 16.
27+ Dim RT_VERSION As New IntPtr( &H10 )
28+ ' Resource name is usually 1.
29+ Dim RES_NAME As New IntPtr( 1 )
30+ ' Use nutral language.
31+ Dim language As UShort = 0
32+
33+ If Not UpdateResource(hUpdate, RT_VERSION, RES_NAME, language, versionResource, CUInt(versionResource.Length)) Then
34+ Throw New System.ComponentModel.Win32Exception()
35+ End If
36+
37+ If Not EndUpdateResource(hUpdate, False ) Then
38+ Throw New System.ComponentModel.Win32Exception()
39+ End If
40+ End Sub
41+
42+ Private Shared Function BuildVersionResource(info As ProgramInfo) As Byte ()
43+ ' Build a minimal VS_VERSION_INFO resource that includes the fixed file info,
44+ ' one StringFileInfo block (with a single StringTable), and a VarFileInfo block.
45+ Using ms As New MemoryStream(), bw As New BinaryWriter(ms)
46+ Dim startPos As Long = ms.Position
47+ bw.Write(CUShort( 0 )) ' wLength (placeholder)
48+ bw.Write(CUShort( 52 )) ' wValueLength = size of VS_FIXEDFILEINFO (52 bytes)
49+ bw.Write(CUShort( 0 )) ' wType = binary
50+ WriteUnicodeString(bw, "VS_VERSION_INFO" )
51+ AlignToDword(bw)
52+
53+ ' --- VS_FIXEDFILEINFO (13 DWORDS: 52 bytes) ---
54+ bw.Write( &HFEEF04BDUI ) ' dwSignature
55+ bw.Write( &H10000UI ) ' dwStrucVersion
56+
57+ Dim versionParts = info.Version.Split( "."c )
58+ Dim major = If (versionParts.Length > 0 , Convert.ToUInt16(versionParts( 0 )), 0 )
59+ Dim minor = If (versionParts.Length > 1 , Convert.ToUInt16(versionParts( 1 )), 0 )
60+ Dim buildPart = If (versionParts.Length > 2 , Convert.ToUInt16(versionParts( 2 )), 0 )
61+ Dim revision = If (versionParts.Length > 3 , Convert.ToUInt16(versionParts( 3 )), 0 )
62+
63+ Dim fileVersionMS = CUInt((major << 16 ) Or minor)
64+ Dim fileVersionLS = CUInt((buildPart << 16 ) Or revision)
65+ bw.Write(fileVersionMS) ' dwFileVersionMS
66+ bw.Write(fileVersionLS) ' dwFileVersionLS
67+ bw.Write(fileVersionMS) ' dwProductVersionMS
68+ bw.Write(fileVersionLS) ' dwProductVersionLS
69+
70+ bw.Write( &H3FUI ) ' dwFileFlagsMask
71+ bw.Write( 0UI ) ' dwFileFlags
72+ bw.Write( &H40004UI ) ' dwFileOS (VOS_NT_WINDOWS32)
73+ bw.Write( 1UI ) ' dwFileType (VFT_APP)
74+ bw.Write( 0UI ) ' dwFileSubtype
75+ bw.Write( 0UI ) ' dwFileDateMS
76+ bw.Write( 0UI ) ' dwFileDateLS
77+
78+ ' --- StringFileInfo block ---
79+ Dim sfiBytes As Byte () = BuildStringFileInfo(info)
80+ bw.Write(sfiBytes)
81+
82+ ' --- VarFileInfo block ---
83+ Dim vfiBytes As Byte () = BuildVarFileInfo()
84+ bw.Write(vfiBytes)
85+
86+ ' Update the top-level wLength
87+ Dim totalLength As UShort = CUShort(ms.Length)
88+ ms.Position = startPos
89+ bw.Write(totalLength)
90+
91+ Return ms.ToArray()
92+ End Using
93+ End Function
94+
95+ Private Shared Sub WriteUnicodeString(bw As BinaryWriter, s As String )
96+ Dim bytes() As Byte = System.Text.Encoding.Unicode.GetBytes(s)
97+ bw.Write(bytes)
98+ bw.Write(CUShort( 0 )) ' null terminator
99+ End Sub
100+
101+ Private Shared Sub AlignToDword(bw As BinaryWriter)
102+ Dim pos As Long = bw.BaseStream.Position
103+ Dim padding As Integer = CInt (( 4 - (pos Mod 4 )) Mod 4 )
104+ For i As Integer = 1 To padding
105+ bw.Write( CByte ( 0 ))
106+ Next
107+ End Sub
108+
109+ Private Shared Function BuildStringFileInfo(info As ProgramInfo) As Byte ()
110+ Using ms As New MemoryStream(), bw As New BinaryWriter(ms)
111+ Dim startPos As Long = ms.Position
112+ bw.Write(CUShort( 0 )) ' wLength (placeholder)
113+ bw.Write(CUShort( 0 )) ' wValueLength = 0 (container)
114+ bw.Write(CUShort( 1 )) ' wType = text
115+ WriteUnicodeString(bw, "StringFileInfo" )
116+ AlignToDword(bw)
117+
118+ Dim stBytes As Byte () = BuildStringTable(info)
119+ bw.Write(stBytes)
120+
121+ Dim lengthValue As UShort = CUShort(ms.Length)
122+ ms.Position = startPos
123+ bw.Write(lengthValue)
124+ Return ms.ToArray()
125+ End Using
126+ End Function
127+
128+ Private Shared Function BuildStringTable(info As ProgramInfo) As Byte ()
129+ Using ms As New MemoryStream(), bw As New BinaryWriter(ms)
130+ Dim startPos As Long = ms.Position
131+ bw.Write(CUShort( 0 )) ' wLength (placeholder)
132+ bw.Write(CUShort( 0 )) ' wValueLength = 0 (container)
133+ bw.Write(CUShort( 1 )) ' wType = text
134+ WriteUnicodeString(bw, "000004B0" ) ' Language and codepage identifier.
135+ AlignToDword(bw)
136+
137+ ' Add string entries.
138+ Dim entries As New List( Of Byte ())
139+ entries.Add(BuildStringEntry( "FileDescription" , info.Description))
140+ entries.Add(BuildStringEntry( "ProductName" , info.Product))
141+ entries.Add(BuildStringEntry( "ProductVersion" , info.Version))
142+ entries.Add(BuildStringEntry( "CompanyName" , info.Company))
143+ entries.Add(BuildStringEntry( "LegalCopyright" , info.Copyright))
144+ entries.Add(BuildStringEntry( "InternalName" , info.Title))
145+
146+ For Each entry As Byte () In entries
147+ bw.Write(entry)
148+ AlignToDword(bw)
149+ Next
150+
151+ Dim lengthValue As UShort = CUShort(ms.Length)
152+ ms.Position = startPos
153+ bw.Write(lengthValue)
154+ Return ms.ToArray()
155+ End Using
156+ End Function
157+
158+ Private Shared Function BuildStringEntry( key As String , value As String ) As Byte ()
159+ Using ms As New MemoryStream(), bw As New BinaryWriter(ms)
160+ Dim startPos As Long = ms.Position
161+ bw.Write(CUShort( 0 )) ' wLength (placeholder)
162+ bw.Write(CUShort(value.Length)) ' wValueLength = number of characters in value
163+ bw.Write(CUShort( 1 )) ' wType = text
164+ WriteUnicodeString(bw, key )
165+ AlignToDword(bw)
166+ WriteUnicodeString(bw, value)
167+ AlignToDword(bw)
168+
169+ Dim lengthValue As UShort = CUShort(ms.Length)
170+ ms.Position = startPos
171+ bw.Write(lengthValue)
172+ Return ms.ToArray()
173+ End Using
174+ End Function
175+
176+ Private Shared Function BuildVarFileInfo() As Byte ()
177+ Using ms As New MemoryStream(), bw As New BinaryWriter(ms)
178+ Dim startPos As Long = ms.Position
179+ bw.Write(CUShort( 0 )) ' wLength (placeholder)
180+ bw.Write(CUShort( 0 )) ' wValueLength = 0 (container)
181+ bw.Write(CUShort( 1 )) ' wType = text
182+ WriteUnicodeString(bw, "VarFileInfo" )
183+ AlignToDword(bw)
184+
185+ Dim transBytes As Byte () = BuildTranslationBlock()
186+ bw.Write(transBytes)
187+
188+ Dim lengthValue As UShort = CUShort(ms.Length)
189+ ms.Position = startPos
190+ bw.Write(lengthValue)
191+ Return ms.ToArray()
192+ End Using
193+ End Function
194+
195+ Private Shared Function BuildTranslationBlock() As Byte ()
196+ Using ms As New MemoryStream(), bw As New BinaryWriter(ms)
197+ Dim startPos As Long = ms.Position
198+ bw.Write(CUShort( 0 )) ' wLength (placeholder)
199+ bw.Write(CUShort( 4 )) ' wValueLength = 4 bytes (two WORDs)
200+ bw.Write(CUShort( 0 )) ' wType = binary
201+ WriteUnicodeString(bw, "Translation" )
202+ AlignToDword(bw)
203+ bw.Write(CUShort( &H0 )) ' Language: nutral
204+ bw.Write(CUShort( &H4B0 )) ' Code page: 1252
205+ AlignToDword(bw)
206+ Dim lengthValue As UShort = CUShort(ms.Length)
207+ ms.Position = startPos
208+ bw.Write(lengthValue)
209+ Return ms.ToArray()
210+ End Using
211+ End Function
212+
213+ End Class
0 commit comments