How to see who is using my Access database over the network?

前端 未结 4 832
终归单人心
终归单人心 2021-01-13 07:04

I actually have 2 questions:

1. How might I see who is using my Access database?

  • E.g: There is someone with an Access database opened and it created
相关标签:
4条回答
  • 2021-01-13 07:13

    Update: Rather than reading and parsing the .ldb/.lacdb file, a better approach would be to use the "User Roster" feature of the Access OLEDB provider as described in the Knowledge Base article

    https://support.microsoft.com/en-us/kb/285822

    and in the other SO question

    Get contents of laccdb file through VBA


    Original answer:

    I put together the following a while ago. It looked promising but then I discovered that computers are not immediately removed from the lock file when they disconnect. Instead, Jet/ACE seems to (internally) mark them as inactive: If ComputerA disconnects and then ComputerB connects, ComputerB overwrites ComputerA's entry in the lock file.

    Still, it does provide a list of sorts. I'm posting it here in case somebody can offer some suggestions for refinement.

    I created two tables in my back-end database:

    Table: [CurrentConnections]
    computerName  Text(255), Primary Key
    
    Table: [ConnectionLog]
    computerName  Text(255), Primary Key
    userName      Text(255)
    

    A VBA Module in my back-end database contained the following code to read (a copy of) the lock file and update the [CurrentConnections] table:

    Public Sub GetCurrentlyConnectedMachines()
        Dim cdb As DAO.Database, rst As DAO.Recordset
        Dim fso As Object  '' FileSystemObject
        Dim lck As Object  '' ADODB.Stream
        Dim lockFileSpec As String, lockFileExt As String, tempFileSpec As String
        Dim buffer() As Byte
    
        Set cdb = CurrentDb
        cdb.Execute "DELETE FROM CurrentConnections", dbFailOnError
        Set rst = cdb.OpenRecordset("SELECT computerName FROM CurrentConnections", dbOpenDynaset)
    
        lockFileSpec = Application.CurrentDb.Name
        If Right(lockFileSpec, 6) = ".accdb" Then
            lockFileExt = ".laccdb"
        Else
            lockFileExt = ".ldb"
        End If
        lockFileSpec = Left(lockFileSpec, InStrRev(lockFileSpec, ".", -1, vbBinaryCompare) - 1) & lockFileExt
    
        '' ADODB.Stream cannot open the lock file in-place, so copy it to %TEMP%
        Set fso = CreateObject("Scripting.FileSystemObject")  '' New FileSystemObject
        tempFileSpec = fso.GetSpecialFolder(2) & "\" & fso.GetTempName
        fso.CopyFile lockFileSpec, tempFileSpec, True
    
        Set lck = CreateObject("ADODB.Stream")  '' New ADODB.Stream
        lck.Type = 1  '' adTypeBinary
        lck.Open
        lck.LoadFromFile tempFileSpec
        Do While Not lck.EOS
            buffer = lck.Read(32)
            rst.AddNew
            rst!computerName = DecodeSZ(buffer)
            rst.Update
            buffer = lck.Read(32)  '' skip accessUserId, (almost) always "Admin"
        Loop
        lck.Close
        Set lck = Nothing
        rst.Close
        Set rst = Nothing
        Set cdb = Nothing
        fso.DeleteFile tempFileSpec
        Set fso = Nothing
    End Sub
    
    Private Function DecodeSZ(buf() As Byte) As String
        Dim b As Variant, rt As String
        rt = ""
        For Each b In buf
            If b = 0 Then
                Exit For  '' null terminates the string
            End If
            rt = rt & Chr(b)
        Next
        DecodeSZ = rt
    End Function
    

    The following code in the Main_Menu form of the front-end database updated the [ConnectionLog] table

    Private Sub Form_Load()
        Dim cdb As DAO.Database, rst As DAO.Recordset
        Dim wshNet As Object  '' WshNetwork
    
        Set wshNet = CreateObject("Wscript.Network")
        Set cdb = CurrentDb
        Set rst = cdb.OpenRecordset("SELECT * FROM ConnectionLog", dbOpenDynaset)
        rst.FindFirst "ComputerName=""" & wshNet.computerName & """"
        If rst.NoMatch Then
            rst.AddNew
            rst!computerName = wshNet.computerName
        Else
            rst.Edit
        End If
        rst!userName = wshNet.userName
        rst.Update
        Set wshNet = Nothing
    End Sub
    

    Finally, the following form in the back-end database listed [its best guess at] the current connections

    ShowActiveUsers

    It is a "continuous forms" form whose Record Source is

    SELECT CurrentConnections.computerName, ConnectionLog.userName 
    FROM CurrentConnections LEFT JOIN ConnectionLog 
        ON CurrentConnections.computerName = ConnectionLog.computerName 
    ORDER BY ConnectionLog.userName; 
    

    and the code-behind is simply

    Private Sub Form_Load()
        UpdateFormData
    End Sub
    
    Private Sub cmdRefresh_Click()
        UpdateFormData
    End Sub
    
    Private Sub UpdateFormData()
        GetCurrentlyConnectedMachines
        Me.Requery
    End Sub
    
    0 讨论(0)
  • 2021-01-13 07:28

    RE: How might I see who is using my Access database? •E.g: There is someone with an Access database opened and it created the .ldb file, I would like to see a list of who opened that database (it could be more than one person).


    Just happened across this while looking for something else, and I thought I might share what I do for this. Note that this assumes that the host computer (the computer on which the database file resides) uses file sharing to provide access to the file.

    You will need to be on the host computer, or have authority to connect to that machine.

    click Start right-click My Computer and select Manage

    if you're not on the host computer, right-click 'Computer Management' and enter the host's name

    Expand 'Shared Folders' and click on 'Open Files' At the right is the list of currently open files with the username for each current user

    0 讨论(0)
  • 2021-01-13 07:34

    Easy. Open the .ldb file in notepad (or any text editor) and you can see the machine names.

    0 讨论(0)
  • 2021-01-13 07:39

    I agree with Gord's Original answer. I used this code on my database, it seems that there is a way around computers not being taken out of CurrentConnections upon exit of the DB.

    I placed this on my main menu form because it is always open until the user exits. I used the unload event on my form to get this to work, and it works awesome! Here is my code

    p.s. Ignore SetWarnings I just have that on so the user doesn't have to click through prompts.

    Private Sub Form_Unload(Cancel As Integer)
    Dim wshNet As Object
    Dim deleteSQL As String
    
    Set wshNet = CreateObject("WScript.Network")
            DoCmd.SetWarnings False
            deleteSQL = "DELETE tblCurrentConnections.* " & _
            "FROM tblCurrentConnections WHERE[computerName] = '" & wshNet.computerName & "';"
                    DoCmd.RunSQL deleteSQL
            DoCmd.SetWarnings True
    End Sub
    
    0 讨论(0)
提交回复
热议问题