[AccessD] CreateObject ("Access.Application") is not working

William Benson vbacreations at gmail.com
Mon Dec 10 13:59:03 CST 2012


Thanks for the replies. I did think I needed to start Access if I could get
to the dbEngine object directly however I was looking for a reason as to
why, should I try to hook the DBEngine, I might not be able to. So I wanted
to be sure Access itself could be launched. Below my function which
follows, is some code from Wayne Phillips, I don't know what it is doing
but it digs into the registry to see which version of Access to launch via
a shell, I think. And it requires that there be a database path to try to
open. I am not sure why there is no way to just launch access and have it
sitting there in the background, without a database (Does
CreateObject doesn't usually require a target "document" but maybe
databases are different?)

Below, I make use of some code from Wayne Phillips to check if Access can
be launched. If it is not already. If it can be, I quit it, since it was me
who launched it. If it was already running, I'll know via GetObject.

Then after I have surety that Access can be launched, I try to use DBEngine.

If I can't then that must be due to reference issues which I am not skilled
enough to overcome as of now but I wanted to at least get to a diagnosis.
The machine I have, does have access, and I can't test this on a lot of
environments.

'My function
Public Function GetDB(strLoc As String) As Object
Dim Ac As Object
Dim GetDBEngine As Object
Dim strName As String
Dim bUseDBE As Boolean

On Error Resume Next
Set Ac = GetObject(, "Access.Application")
If Ac Is Nothing Then
    Set Ac = CreateAccessInstance("Access.Application.15", strLoc)
    If Ac Is Nothing Then
        Set Ac = CreateAccessInstance("Access.Application.14", strLoc)
        If Ac Is Nothing Then
            Set Ac = CreateAccessInstance("Access.Application.12", strLoc)
            If Ac Is Nothing Then
                If UCase(Right(strLoc, 6)) = ".ACCDB" Then
                    'No sense trying to use DBEngine
                    Exit Function
                End If
            End If
        End If
    End If
    If Not Ac Is Nothing Then
        Debug.Print "We started Access, we can kill it"
        Ac.Quit
        bUseDBE = True
    End If
Else
    bUseDBE = True
End If
If bUseDBE Then
    Err.Clear
    Debug.Print "Trying to get the target through the DBEngine, and no
other db was open"
    'try 120
    Err.Clear
    Set GetDBEngine = CreateObject("DAO.DBEngine.120")
    If Err.Number <> 0 Then 'try 36
      Err.Clear
      Set GetDBEngine = CreateObject("DAO.DBEngine.36")
      If Err.Number <> 0 Then
        Set GetDBEngine = CreateObject("DAO.DBEngine.35")
      End If
    End If
    If Not GetDBEngine Is Nothing Then
        Set GetDB = GetDBEngine.Workspaces(0).OpenDatabase(strLoc)
    End If
End If
If bUseDBE And GetDB Is Nothing Then
    'Something is wrong - we can start and/or had an instance of Access but
    'cannot hook the database engine
    MsgBox "There is a problem with launching the database engine"
ElseIf Not bUseDBE Then
    Err.Clear
    Debug.Print "Trying to get the target through the DBEngine, and no
other db was open"
    'try 120
    Err.Clear
    Set GetDBEngine = CreateObject("DAO.DBEngine.120")
    If Err.Number <> 0 Then 'try 36
      Err.Clear
      Set GetDBEngine = CreateObject("DAO.DBEngine.36")
      If Err.Number <> 0 Then
        Set GetDBEngine = CreateObject("DAO.DBEngine.35")
      End If
    End If
    If Not GetDBEngine Is Nothing Then
        Set GetDB = GetDBEngine.Workspaces(0).OpenDatabase(strLoc)
    End If
    If GetDB Is Nothing Then
        MsgBox "Cannot find Access on this machine nor do the libraries for
DAO appear to be installed or registered within this application."
    End If
End If

End Function


Option Explicit

' ModCreateOfficeInstance by Wayne Phillips 2005 - © EverythingAccess.com
' Written on 23/11/2005 for automating a specific version of Access
' Updated on 07/03/2012 to allow for delayed binding and better error
handling.

Private Declare Function RegCloseKey Lib "advapi32" _
                        (ByVal hKey As Long) As Long

Private Declare Function RegOpenKey Lib "advapi32" _
                         Alias "RegOpenKeyA" _
                        (ByVal hKey As Long, _
                         ByVal sSubKey As String, _
                         hKey As Long) As Long

Private Declare Function RegQueryValueEx Lib "advapi32" _
                         Alias "RegQueryValueExA" _
                        (ByVal hKey As Long, _
                         ByVal sKeyValue As String, _
                         ByVal lpReserved As Long, _
                         lpType As Long, _
                         lpData As Any, _
                         nSizeData As Long) As Long

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Function FnGetRegString(ByVal hKeyRoot As Long, _
                        ByVal strSubKey As String, _
                        ByVal strValueName As String, _
                        ByRef strRetVal As String) As Boolean

    Dim lngDataSize As Long
    Dim hKey As Long

    Const ERROR_MORE_DATA = 234
    Const ERROR_SUCCESS = 0

    strRetVal = ""

    If RegOpenKey(hKeyRoot, _
                 strSubKey, _
                 hKey) = ERROR_SUCCESS Then

        'Calculate the length of string we need to initialize as a buffer...
        If RegQueryValueEx(hKey, _
                         strValueName, _
                         0&, _
                         0&, _
                         ByVal strRetVal, _
                         lngDataSize) = ERROR_MORE_DATA Then

            'Initialize the string buffer to a fixed length
            strRetVal = String(lngDataSize + 1, 0)

            If RegQueryValueEx(hKey, _
                        strValueName, _
                        0&, _
                        0&, _
                        ByVal strRetVal, _
                        lngDataSize) = ERROR_SUCCESS Then

                'We got the value, trim the extra null terminator
                strRetVal = Left(strRetVal, InStr(1, strRetVal, Chr(0)) - 1)
                FnGetRegString = True

            End If

        End If

        Call RegCloseKey(hKey)

    End If

End Function

Private Function FnGetAssociatedPathFromProgID(ByVal strProgID As String)
As String

    Dim strOutputPath As String

    Const HKEY_CLASSES_ROOT = &H80000000

    If FnGetRegString(HKEY_CLASSES_ROOT, strProgID & "\shell\Open\command",
"", strOutputPath) = True Then
        FnGetAssociatedPathFromProgID = strOutputPath
    End If

End Function

Public Function CreateOfficeInstance(ByVal strProgID As String, _
                            ByVal strFilePath) As Object

    Dim strCommandLine As String
    Dim strPath As String

    'Get the class GUID (CLSID) from the input ProgID
    strPath = FnGetAssociatedPathFromProgID(strProgID)

    If Len(strPath) > 0 Then

        'The returned path is actually a command line string with parameter
for file name as %1
        strCommandLine = Replace(strPath, "%1", strFilePath)

        Shell strCommandLine, vbMinimizedNoFocus

        'Attempt to bind to the instance...
        On Error GoTo RetryDelay
        Set CreateOfficeInstance = GetObject(strFilePath).Application

    Else

        Err.Raise 76, , "CreateOfficeInstance: failed to get path
information for ProgID '" & strProgID & "'"

    End If

    Exit Function

RetryDelay:

    ' Binding to the created instance might fail if the external process
hasn't yet loaded the
    ' document / file and registered itself in the COM Running Object
Table, so we will retry
    ' several times after a short delay, before failing.

    Dim RetryCount As Long
    If RetryCount < 10 Then
        Sleep 500   ' Wait half a second and try again (upto 10 times)
        RetryCount = RetryCount + 1
        Resume
    Else
        On Error GoTo 0
        Err.Raise 429, , "CreateOfficeInstance: failed to bind to specific
instance of '" & strProgID & "'"
    End If

End Function


More information about the AccessD mailing list