Access

Solo permita que se ejecute una instancia de una base de datos a la vez

¿Alguna vez ha tenido uno de esos usuarios que abren la base de datos, hace otras cosas, regresa y abre otra instancia … y así va.

Tal vez es hora de minimizar los problemas que esto puede causar al limitar a un usuario solo poder lanzar una sola instancia de una base de datos determinada.

Usando su script de lanzamiento

Si ha configurado correctamente a sus usuarios y tienen su propia copia privada de la base de datos front-end, entonces la técnica más fácil para evitar que inicie múltiples instancias de su base de datos tal vez sea a través del script de lanzamiento.

Un VBScript simple para iniciar una base de datos de Microsoft Access puede verse algo así como:

Option Explicit
Dim oAccess

' Create Access Application object
Set oAccess = CreateObject("Access.Application")

' Make Access visible
oAccess.Visible = True
oAccess.UserControl = True

' Open the database
oAccess.OpenCurrentDatabase "C:\Databases\Demos\OnlyLaunchOnce.accdb"

' Cleanup
Set oAccess = Nothing

Ahora, si quisiéramos evitar que se inicie otra instancia de esa base de datos, la solución más simple sería verificar primero la existencia de un archivo de bloqueo de acceso (LDB, LACCDB) y modificaría lo anterior para ser más como:

Option Explicit
Dim oFSO, oAccess, dbPath, laccdbPath

' Set the path to your Access database file
dbPath = "C:\Databases\Demos\OnlyLaunchOnce.accdb"

' Construct the path for the .laccdb lock file
laccdbPath = Replace(dbPath, ".accdb", ".laccdb")

' Create FileSystemObject
Set oFSO= CreateObject("Scripting.FileSystemObject")

' Check if .laccdb file exists
If oFSO.FileExists(laccdbPath) Then
    WScript.Echo "The database is already runnings."
Else
    ' Create Access Application object
    Set oAccess = CreateObject("Access.Application")
    
    ' Make Access visible
    oAccess.Visible = True
    oAccess.UserControl = True

    ' Open the database
    oAccess.OpenCurrentDatabase dbPath
End If

' Cleanup
Set oFSO = Nothing
Set oAccess = Nothing

Uso del código desde su base de datos

Otra forma de manejar esto podría ser validar que cuando se lance el mismo título de la ventana se encuentra en la lista de ventanas de aplicaciones abiertas. Para esto, debemos girar hacia el uso de un par de API de Windows y haríamos algo como:

Private Declare PtrSafe Function EnumWindows Lib "user32" (ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As LongPtr, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare PtrSafe Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hWnd As LongPtr) As Long
Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hWnd As LongPtr) As Boolean

Private colWindowTexts        As Collection


Function GetCurrentWindowTitle() As String
    Dim lHWnd                 As LongPtr
    Dim lWindowTextLength     As Long
    Dim sWindowText           As String

    lHWnd = GetActiveWindow()
    lWindowTextLength = GetWindowTextLength(lHWnd)
    sWindowText = Space$(lWindowTextLength + 1)
    GetWindowText lHWnd, sWindowText, lWindowTextLength + 1

    GetCurrentWindowTitle = Left$(sWindowText, lWindowTextLength)
End Function

Private Function EnumWindowsCallback(ByVal lHWnd As LongPtr, _
                                     ByVal lParam As LongPtr) As Long
    Dim sWindowText           As String * 255
    Dim lWindowTextLength     As Long

    lWindowTextLength = GetWindowText(lHWnd, sWindowText, Len(sWindowText))

    If lWindowTextLength > 0 And IsWindowVisible(lHWnd) Then
        sWindowText = Left(sWindowText, lWindowTextLength)
        colWindowTexts.Add Trim(sWindowText)
    End If

    EnumWindowsCallback = 1
End Function

Function CountWindowsWithTitle(sTitle As String) As Long
    Dim sWindowText           As Variant

    Set colWindowTexts = New Collection

    EnumWindows AddressOf EnumWindowsCallback, 0

    For Each sWindowText In colWindowTexts
        'Debug.Print Trim(sWindowText)    'For debugging purposed
        If Trim(sWindowText) = sTitle Then
            CountWindowsWithTitle = CountWindowsWithTitle + 1
        End If
    Next sWindowText

    Set colWindowTexts = Nothing
End Function

Luego, utilizando un formulario de inicio o una macro AutoExec, simplemente realizaríamos la verificación haciendo:

    If CountWindowsWithTitle(GetCurrentWindowTitle()) > 1 Then ' Already an instance running
        MsgBox "The database is already open.", vbInformation, "Database Already Running"
        Application.Quit acQuitSaveNone
    End If

Conclusión

Entonces, arriba he proporcionado 2 posibles formas de evitar que los usuarios abran múltiples instancias de la misma base de datos, la elección es suya.

Al tomar tales pasos, en última instancia, está reduciendo la posibilidad de que ocurran confusión y errores, ayudando con el consumo general de recursos, lo que puede afectar el rendimiento general de la base de datos y las PC e incluso evitar problemas de integridad de datos que surgen de los conflictos de datos y la posible pérdida de cambios de tener los mismos cambios de tener los mismos cambios en tener los mismos cambios. Los registros se abren en diferentes casos de Databaase.

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Mira también
Cerrar
Botón volver arriba