Provided by Allen Browne, August 2006. (Updated December 2007.)
Code for Splash screen with version information
This page contains the VBA code from the Splash screen with Version information utility, for use in your Access application.
Option Compare Database
Option Explicit
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)
Private Const MAX_PATH As Integer = 255
Private Declare Function apiGetSystemDirectory& Lib "kernel32" Alias "GetSystemDirectoryA" _
(ByVal lpBuffer As String, ByVal nSize As Long)
Private Declare Function apiGetWindowsDirectory& Lib "kernel32" Alias "GetWindowsDirectoryA" _
(ByVal lpBuffer As String, ByVal nSize As Long)
Private Declare Function apiGetTempDir Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, _
ByVal lpBuffer As String) As Long
Private Declare Function apiGetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Private Declare Function apiGetComputerName Lib "kernel32" Alias _
"GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Private Const conMod = "ajbVersion"
Public Function InitSplash()
On Error GoTo Err_Handler
Static sbRunning As Boolean
Dim dtEndTime As Date
Const strcSplashForm = "frmHelpAbout"
Const strcNextForm = "Switchboard"
Const lngcSeconds = 2&
If sbRunning Then
Exit Function
End If
sbRunning = True
DoCmd.OpenForm strcSplashForm
With Forms(strcSplashForm)
.SetFocus
.Recalc
.Repaint
End With
dtEndTime = DateAdd("s", lngcSeconds, Now())
Do While Now() < dtEndTime
DoEvents
Loop
Call ForceClosed(strcSplashForm)
If strcNextForm <> vbNullString Then
DoCmd.OpenForm strcNextForm
End If
sbRunning = False
Exit_Handler:
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, conMod & ".InitSplash")
Resume Exit_Handler
End Function
Public Function GetAccessVersion(Optional db As DAO.Database) As String
On Error Resume Next
GetAccessVersion = fGetProductVersion(SysCmd(acSysCmdAccessDir) & "msaccess.exe")
End Function
Public Function GetFileFormat(Optional db As DAO.Database) As String
On Error GoTo Err_Handler
Dim bResetDb As Boolean
Dim bIsCompiledOnly As Boolean
Dim bIsProject As Boolean
Dim strReturn As String
If db Is Nothing Then
bResetDb = True
Set db = DBEngine(0)(0)
End If
Select Case Int(Val(db.Version))
Case 3
strReturn = "97 MD"
Case 4
Select Case db.Properties("AccessVersion")
Case "08.50"
strReturn = "2000"
Case "09.50"
strReturn = "2002/3"
End Select
If strReturn <> vbNullString Then
bIsProject = Eval("(CurrentProject.ProjectType = 1)")
If bIsProject Then
strReturn = strReturn & " AD"
Else
strReturn = strReturn & " MD"
End If
End If
Case 12
strReturn = "2007 ACCD"
End Select
bIsCompiledOnly = (db.Properties("MDE") = "T")
If bIsCompiledOnly Then
strReturn = strReturn & "E"
Else
strReturn = strReturn & "B"
End If
If strReturn <> vbNullString Then
GetFileFormat = strReturn
End If
Exit_Handler:
On Error Resume Next
If bResetDb Then
Set db = Nothing
End If
Exit Function
Err_Handler:
Select Case Err.Number
Case 2482&, 3270&
Resume Next
Case Else
Call LogError(Err.Number, Err.Description, conMod & ".GetFileFormat")
Resume Exit_Handler
End Select
End Function
Public Function GetJetVersion(Optional db As DAO.Database) As String
On Error GoTo Err_Handler
Dim bResetDb As Boolean
Dim strJetFile As String
If db Is Nothing Then
bResetDb = True
Set db = DBEngine(0)(0)
End If
Select Case Int(Val(db.Version))
Case 3
strJetFile = fReturnSysDir() & "\msjet35.dll"
Case 4
strJetFile = fReturnSysDir() & "\msjet40.dll"
Case 12
strJetFile = Environ("CommonProgramFiles")
If strJetFile = vbNullString Then
strJetFile = TrailingSlash(Environ("ProgramFiles")) & "Common Files"
End If
strJetFile = TrailingSlash(strJetFile) & "Microsoft Shared\Office12\acecore.dll"
End Select
If bResetDb Then
Set db = Nothing
End If
If strJetFile <> vbNullString Then
GetJetVersion = fGetProductVersion(strJetFile)
End If
Exit_Handler:
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, conMod & ".GetJetVersion")
Resume Exit_Handler
End Function
Public Function GetDataPath(strTable As String) As String
On Error GoTo Err_Handler
Dim varArray As Variant
Dim i As Integer
If Trim$(strTable) <> vbNullString Then
varArray = Split(CurrentDb.TableDefs(strTable).Connect, ";")
For i = LBound(varArray) To UBound(varArray)
If varArray(i) Like "DATABASE=*" Then
GetDataPath = Trim$(Mid$(varArray(i), 10))
Exit For
End If
Next
End If
Exit_Handler:
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, conMod & ".GetDataPath", strTable, False)
GetDataPath = "#Error"
Resume Exit_Handler
End Function
Public Function GetNetworkUserName() As String
On Error GoTo Err_Handler
Dim lngLen As Long
Dim lngX As Long
Dim strUserName As String
strUserName = String$(254, 0&)
lngLen = 255&
lngX = apiGetUserName(strUserName, lngLen)
If (lngX > 0&) Then
strUserName = Left$(strUserName, lngLen - 1&)
End If
If strUserName <> vbNullString Then
GetNetworkUserName = strUserName
Else
GetNetworkUserName = "{unknown}"
End If
Exit_Handler:
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, conMod & ".fOSUserName")
Resume Exit_Handler
End Function
Public Function GetMachineName() As String
On Error GoTo Err_Handler
Dim lngLen As Long
Dim lngX As Long
Dim strCompName As String
lngLen = 16&
strCompName = String$(lngLen, 0&)
lngX = apiGetComputerName(strCompName, lngLen)
If lngX <> 0& Then
GetMachineName = Left$(strCompName, lngLen)
Else
GetMachineName = "{unknown}"
End If
Exit_Handler:
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, conMod & ".GetMachineName")
Resume Exit_Handler
End Function
Public Function ForceClosed(strDoc As String, Optional bIsReport As Boolean) As Boolean
On Error Resume Next
DoCmd.Close IIf(bIsReport, acReport, acForm), strDoc, acSaveNo
ForceClosed = (Err.Number = 0&)
End Function
Private 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
Private Function fReturnTempDir() As String
Dim strTempDir As String
Dim lngX As Long
strTempDir = String$(MAX_PATH, 0)
lngX = apiGetTempDir(MAX_PATH, strTempDir)
If lngX <> 0& Then
fReturnTempDir = Left$(strTempDir, lngX)
End If
End Function
Private Function fReturnSysDir() As String
Dim strSysDirName As String
Dim lngX As Long
strSysDirName = String$(MAX_PATH, 0)
lngX = apiGetSystemDirectory(strSysDirName, MAX_PATH)
If lngX <> 0& Then
fReturnSysDir = Left$(strSysDirName, lngX)
End If
End Function
Private Function fReturnWinDir() As String
Dim strWinDirName As String
Dim lngX As Long
strWinDirName = String$(MAX_PATH, 0)
lngX = apiGetWindowsDirectory(strWinDirName, MAX_PATH)
If lngX <> 0& Then
fReturnWinDir = Left$(strWinDirName, lngX)
End If
End Function
Private Function LogError(ByVal lngErrNumber As Long, ByVal strErrDescription As String, _
strCallingProc As String, Optional vParameters, Optional bShowUser As Boolean = True) As Boolean
On Error GoTo Err_LogError
Dim strMsg As String
Select Case lngErrNumber
Case 0&
Debug.Print strCallingProc & " called error 0."
Case 2501&
Case 3314&, 2101&, 2115&
If bShowUser Then
strMsg = "Record cannot be saved at this time." & vbCrLf & _
"Complete the entry, or press <Esc> to undo."
MsgBox strMsg, vbExclamation, strCallingProc
End If
Case Else
If bShowUser Then
strMsg = "Error " & lngErrNumber & ": " & strErrDescription
MsgBox strMsg, vbExclamation, strCallingProc
End If
LogError = True
End Select
Exit_LogError:
Exit Function
Err_LogError:
strMsg = "An unexpected situation arose in your program." & vbCrLf & _
"Please write down the following details:" & vbCrLf & vbCrLf & _
"Calling Proc: " & strCallingProc & vbCrLf & _
"Error Number " & lngErrNumber & vbCrLf & strErrDescription & vbCrLf & vbCrLf & _
"Unable to record because Error " & Err.Number & vbCrLf & Err.Description
MsgBox strMsg, vbCritical, "LogError()"
Resume Exit_LogError
End Function
Function TrailingSlash(varIn As Variant) As String
If Len(varIn) > 0 Then
If Right(varIn, 1) = "\" Then
TrailingSlash = varIn
Else
TrailingSlash = varIn & "\"
End If
End If
End Function