0

(もう一度) MS Access に問題があります。Access には、たとえば vba コードでエラーが発生した場合にオブジェクト参照が失われるという、やや特殊な習慣があります。ほとんどの場合はうまくいくように見えますが、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

User-Object は起動時に一度初期化され、ハンドルが保存されます。ユーザー情報は、プロパティ msCurrentUser を通じて取得できます。私が言ったように、これはほとんどの場合うまくいきますが、 CopyMemoryが失敗する特定のケースがあるようです。どんな助けでも大歓迎です。

前もって感謝します

ジョン

4

1 に答える 1

4

真剣に、そうしないでください。面倒ですが、必要に応じてオブジェクトを再作成する必要があります。現在、オブジェクト参照、つまりメモリ内の特定の場所へのポインタ (*) をキャッシュしています。未処理のエラーによってオブジェクトが破棄された場合、オペレーティング システム (または Access の内部メモリ マネージャー) は、以前にオブジェクトが占有していたメモリ (つまり、参照が指すメモリ) をすぐに再利用することはほとんどありません。コードは時々動作するようです。ただし、「機能する」場合でも、実際には古いポインターを参照しています。

(*) Access オブジェクト参照がボンネットの下の COM/IUnknown ポインターであることを考えると、実際には複数のレベルの間接性がありますが、1 つの観点から単純化するだけで十分です。

于 2013-11-13T10:41:08.753 に答える