Microsoft hasn't provided any way for us to programmatically detect
whether a particular patch (like Office Service Packs) is installed or not.
One workaround this limitation is to read off the version information
stored in the actual Office executables themselves. The following table
lists the version information retrieved by running this code on one of my and
one of Doug Ware's system.
Exe Name |
|
Office 2000 |
|
Office 2000 SR1 |
|
Office XP |
|
Office XP SP1 |
|
Office XP SP2 |
|
MsAccess.exe |
|
9.0.0.2719 |
|
9.0.0.3822 |
|
10.0.2627.1 |
|
10.0.3409.0 |
|
10.0.4302.0 |
WinWord.exe |
|
9.0.0.2717 |
|
9.0.0.3822 |
|
10.0.2627.0 |
|
10.0.3416.0 |
|
10.0.4219.0 |
Excel.Exe |
|
9.0.0.2719 |
|
9.0.0.3822 |
|
10.0.2614.0 |
|
10.0.3506.0 |
|
10.0.4302.0 |
FrontPage.exe |
|
4.0.2.2717 |
|
4.0.2.3821 |
|
10.0.2623.0 |
|
10.0.3402.0 |
|
10.0.4128.0 |
Outlook.exe |
|
9.0.0.2416 |
|
9.0.0.2416 |
|
10.0.2627.1 |
|
10.0.3416.0 |
|
10.0.4024.0 |
PowerPnt.exe |
|
9.0.0.2716 |
|
9.0.0.3821 |
|
10.0.2623.0 |
|
10.0.3506.0 |
|
10.0.4205.0 |
WinProj.exe |
|
8.0.98.407 |
|
unknown |
|
unknown |
|
unknown |
|
unknown |
Private Type VS_FIXEDFILEINFO
dwSignature As Long
dwStrucVersion As Long
dwFileVersionMS As Long
dwFileVersionLS As Long
dwProductVersionLS As Long
dwFileFlagsMask As Long
dwProductVersionMS As Long
dwFileFlags As Long
dwFileOS As Long
dwFileType As Long
dwFileSubtype As Long
dwFileDateMS As Long
dwFileDateLS As Long
End Type
Private Declare Function apiGetFileVersionInfoSize _
Lib "version.dll" Alias "GetFileVersionInfoSizeA" _
(ByVal lptstrFilename As String, _
lpdwHandle As Long) _
As Long
Private Declare Function apiGetFileVersionInfo 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 apiVerQueryValue Lib _
"version.dll" Alias "VerQueryValueA" _
(pBlock As Any, _
ByVal lpSubBlock As String, _
lplpBuffer As Long, _
puLen As Long) _
As Long
Private Declare Sub sapiCopyMem _
Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)
Function fGetProductVersion(strExeFullPath As String) As String
On Error GoTo ErrHandler
Dim lngSize As Long
Dim lngRet As Long
Dim pBlock() As Byte
Dim lpfi As VS_FIXEDFILEINFO
Dim lppBlock As Long
lngSize = apiGetFileVersionInfoSize( _
strExeFullPath, _
lngRet)
If lngSize Then
ReDim pBlock(lngSize)
lngRet = apiGetFileVersionInfo(strExeFullPath, 0, _
lngSize, pBlock(0))
If Not lngRet = 0 Then
lngRet = apiVerQueryValue(pBlock(0), _
"\", lppBlock, lngSize)
Call sapiCopyMem(lpfi, ByVal lppBlock, lngSize)
With lpfi
fGetProductVersion = HIWord(.dwFileVersionMS) & "." & _
LOWord(.dwFileVersionMS) & "." & _
HIWord(.dwFileVersionLS) & "." & _
LOWord(.dwFileVersionLS)
End With
End If
End If
ExitHere:
Erase pBlock
Exit Function
ErrHandler:
Resume ExitHere
End Function
Private Function LOWord(dw As Long) As Integer
If dw And &H8000& Then
LOWord = dw Or &HFFFF0000
Else
LOWord = dw And &HFFFF&
End If
End Function
Private Function HIWord(dw As Long) As Integer
HIWord = (dw And &HFFFF0000) \ &H10000
End Function
|