访问:在程序重置期间保持COM引用?

时间:2010-10-01 01:57:57

标签: ms-access vba com ms-access-2003

Access VBA(2003)中是否有方法将COM引用转换为整数,并调用AddRef / Release? (它给出错误“标记为受限制的函数或接口,或者该函数使用Visual Basic中不支持的自动化类型”)

我正在使用第三方COM对象,它不能处理在单个进程中实例化两次(这是一个已知错误)。因此,我考虑将引用存储为隐藏表单上的控件标题,以防止程序重置清除所有VB变量。

编辑:我认为可以使用未记录的ObjPtr完成对int的强制转换,然后使用CopyMemory API再次返回,并且可以隐式调用AddRef / Release。但有更好的方法吗?加载项是否受程序重置保护?

1 个答案:

答案 0 :(得分:0)

代码重置后是否存在问题,或者一旦代码重置,它是否无法重新初始化?

对于第一个问题,将顶级对象包装在函数中并在内部使用STATIC变量来缓存引用。如果STATIC变量为Nothing,则重新初始化。这是我用来缓存对本地数据库的引用的函数:

  Public Function dbLocal(Optional bolInitialize As Boolean = True) +
     As DAO.Database
  ' 2003/02/08 DWF added comments to explain it to myself!
  ' 2005/03/18 DWF changed to use Static variable instead
  ' uses GoTos instead of If/Then because:
  '  error of dbCurrent not being Nothing but dbCurrent being closed (3420)
  '  would then be jumping back into the middle of an If/Then statement
  On Error GoTo errHandler
    Static dbCurrent As DAO.Database
    Dim strTest As String

  If Not bolInitialize Then GoTo closeDB

  retryDB:
    If dbCurrent Is Nothing Then
       Set dbCurrent = CurrentDb()
    End If
    ' now that we know the db variable is not Nothing, test if it's Open
    strTest = dbCurrent.Name

  exitRoutine:
    Set dbLocal = dbCurrent
    Exit Function

  closeDB:
    If Not (dbCurrent Is Nothing) Then
       Set dbCurrent = Nothing
    End If
    GoTo exitRoutine

  errHandler:
    Select Case err.Number
      Case 3420 ' Object invalid or no longer set.
        Set dbCurrent = Nothing
        If bolInitialize Then
           Resume retryDB
        Else
           Resume closeDB
        End If
      Case Else
        MsgBox err.Number & ": " & err.Description, vbExclamation, "Error in dbLocal()"
        Resume exitRoutine
    End Select
  End Function

您在代码中的任何一个位置:

  Dim db As DAO.Database
  Set db = CurrentDB()
  Set db = DBEngine(0)(0)
  db.Execute "[SQL DML]", dbFailOnError

...你可以用以下内容替换整个内容:

  dbLocal.Execute "[SQL DML]", dbFailOnError

...您不必担心在应用程序打开时或代码重置后初始化它 - 它会自我修复,因为它会检查静态内部变量并在需要时重新初始化。

唯一需要注意的是,当您关闭应用程序时,需要将bolInitialize参数设置为False进行调用,因为这样可以清除引用,因此当应用程序超出范围时,不存在应用程序挂起的风险app关闭。

对于另一个问题,我真的怀疑VBA中有任何解决方案,除非你可以进行API调用并终止外部进程。但我认为这是一个长镜头。