0

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

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

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

4

1 回答 1

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 进行调用,因为这会清理引用,因此当应用程序关闭时超出范围时应用程序不会挂起。

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

于 2010-10-01T03:20:59.060 回答