【问题标题】:MS Access problems with API and CopyMemoryAPI 和 CopyMemory 的 MS Access 问题
【发布时间】:2013-11-25 20:36:04
【问题描述】:

我(再次)遇到了 MS Access 的问题。例如,如果 vba 代码中发生错误,Access 有一些特殊的习惯会释放对象引用。我找到了一个非常巧妙的解决方案来解决这个问题,它似乎在大多数情况下都有效,但有时会导致 Access 崩溃。

Public CurrentUser As CUser 'CUser is a class containing Userinformation

Private Const C_USER_STORAGENAME As String = "CURRENTUSER_HANDLEID"

Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (destination As Any, source As Any, ByVal length As LongPtr)

Private Const rbHandleProp = C_USER_STORAGENAME

Public Function InitUser() As Integer
    Dim lngUserPtr As LongPtr
    Set CurrentUser = New CUser                    'Cache a copy
    CurrentUser.InitializeUser
    lngUserPtr = ObjPtr(CurrentUser)                'HandleID
    WriteProjProperty rbHandleProp, lngUserPtr      'Write HandleID
End Function

Private Sub WriteProjProperty(key As String, Value As Variant)
    On Error Resume Next
    CurrentProject.Properties(key).Value = Value
    If err.Number = 2455 Then 'No Key!
        CurrentProject.Properties.Add key, Value
    End If
End Sub

Private Function GetCurrentUser(lngUserPtr As LongPtr) As Object
   Dim objUser As Object

   CopyMemory objUser, lngUserPtr, 4 'CRASHES HERE SOMETIMES
   Set GetCurrentUser = objUser
   Set objUser = Nothing
End Function

Public Function ReadProjProperty(key As String) As Variant
    On Error Resume Next
    ReadProjProperty = CurrentProject.Properties(key).Value
End Function

Property Get msCurrentUser() As CUser
    If CurrentUser Is Nothing Then
        Set CurrentUser = GetCurrentUser(CLng(ReadProjProperty(rbHandleProp)))
    End If
    Set msCurrentUser = CurrentUser
End Property

用户对象在启动时初始化一次并保存句柄。用户信息可以通过属性 msCurrentUser 获取。正如我所说,这在大多数情况下都有效,但似乎在某些情况下 CopyMemory 会失败。任何帮助将不胜感激。

提前致谢

乔恩

【问题讨论】:

  • 您传递地址而不是参考是否有特定原因?

标签: api vba ms-access copymemory


【解决方案1】:

说真的,不要那样做——这很痛苦,但你只需要根据需要重新创建对象。目前,您正在缓存对象引用,即指向内存中特定位置的指针 (*)。当一个未处理的错误导致对象被销毁时,操作系统(或 Access 的内部内存管理器)不太可能立即重用该对象之前占用的内存(即引用指向的内存),这就是为什么你的代码有时似乎可以工作。然而,即使它确实“工作”了,实际上你也在尊重一个过时的指针。

(*) 实际上有不止一级间接,因为 Access 对象引用是引擎盖下的 COM/IUnknown 指针,但简化为一级就足以说明这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多