Example Apps for Businesses, Schools & Developers

Versions 2.21 / 2.5           Approx 3.5 MB (zipped)                 First Published 27 Mar 2024                 Last Updated 28 Apr 2024


Preamble

This is the second part of a series on protecting the design and data in your database objects.
The first article, Protect Data in Tables and Queries demonstrated how tables and queries can be made READ ONLY whilst allowing users to work normally with forms.

As previously stated, end users should NEVER have direct access to tables or queries via the navigation pane. All user interaction should be done using forms.

In my databases, unless otherwise specified by the client, the navigation pane and ribbon are hidden and other basic security measures applied.
This is usually enough to prevent unintentional damage to database objects.

However, users who know enough to be 'dangerous' will be able to circumvent simple Access security and, in some cases, cause problems due to 'meddling'.
In my experience, significant damage can be caused by interested users who just want to explore how databases work with no malicious intent.

It is standard practice to split databases with the Access front end distributed as an ACCDE file. Doing this will protect your code and the design of forms / reports.
Also, the design of linked backend tables cannot be altered from the frontend database.

However, that will not prevent users editing or deleting records in tables or queries or exporting the data to e.g. Excel or text files.
Nor will it prevent users changing the design of any tables or queries in the front end database.

This article describes ways of helping to protect all database objects from unintentional tampering by users.



Downloads

Click to download - ACCDB or 32/64-bit ACCDE (all files are approx 3.5 MB and zipped):

          LockDownDatabaseObjects_v2.21       ACCDB file

          LockDownDatabaseObjects_v2.21       32-bit ACCDE file

          LockDownDatabaseObjects_v2.21       64-bit ACCDE file

The ACCDB file has deliberately not been fully locked down so you can explore how it works. There are additional restrictions in the ACCDE versions.



Example App

The example app opens to a startup form, frmStart, which outlines what the app does.

StartForm
The app has almost identical objects to the example app in the previous article.

In any standard Access app, the right click context menus give users many options to choose from.
For example, using an English language version of Access 365:

Table

DefaultTableContextMenu
Query

DefaultQueryContextMenu


However, in this example app, right clicking on any table or query displays a reduced context menu with many items hidden and all other items disabled.

Table

TableContextMenu
Query

QueryContextMenu


NOTE: See important comments below about different Access versions and Office languages other than English.

For forms, the only available option is Open and for reports Open / Print / Print Preview.

Form

FormContextMenu
Report

ReportContextMenu


Macros and modules are all hidden in the navigation pane but, if they are made visible, the context menus are also disabled.

Macro

MacroContextMenu
Module

ModuleContextMenu


The above restrictions mean that users cannot view or edit the design of objects, nor export them. This applies to both ACCDB and ACCDE files.

NOTE:
In the ACCDE versions of the example app, the right click context menus have been completely removed for all database objects

It is possible to open any database object by double clicking in the navigation pane.
However, whilst forms and reports open normally, tables and queries will close again in about half a second.
The code is able to distinguish between different objects with the same name and treat each object type correctly.

Other Restrictions:
a)   Objects cannot be accessed from the ribbon as those items are disabled
b)   The status bar has been removed preventing changes to design view
c)   The Visual Basic Editor is highly locked down. If you attempt to open it directly or via the Immediate window, it will immediately close
d)   The shift bypass has been disabled.




How does the Example App work?

Once again, the app makes use of the fact that when viewing the data in tables and queries, you are actually viewing a datasheet form.
This means that certain events / actions / properties can be controlled using code.

The code checks for any datasheet (table or query) which is currently open and active.
It then closes the table / query immediately after it is opened.
The following code should be placed in a standard module e.g. modSecurity

CODE:

Public Function BlockViewTableQuery()

Dim frm As Object, I As Integer

'determine if object is within scope (table / query)
On Error Resume Next

      'restrict use of VBE
      CloseAllVBEWindows

      'create an error to exclude datasheet forms
      If Err = 0 Then Debug.Print Screen.ActiveDatasheet.Properties("linkchildfields").Value

      'set frm to active datasheet table/query if no error triggered above
      If Err = 0 Then Set frm = Screen.ActiveDatasheet Else Exit Function

      If Application.CurrentObjectName = frm.Name Then
            DoCmd.Close acTable, frm.Name
            DoCmd.Close acQuery, frm.Name
      End If

End Function


The code first closes any VBE windows that may have been opened. See my article Close All VBE Windows for details of this function

As in the earlier version of this example app, the code is called from a hidden form (frmHide) which is loaded when the app starts.
A timer event is used with a short interval to check for the currently active datasheet and close it

Private Sub Form_Timer()/span>
      Call SetTableQueryReadOnly/span>
End Sub/span>


Once again I have used an interval of 500 milliseconds (0.5 s) but this can be altered as required.

Many thanks to fellow Access developers, Chris Arnold and Xevi Batlle, both of whom tested earlier versions of this app and suggested several useful improvements.

The significantly reduced context menus used in the ACCDB version of this app were achieved in two ways:

a)   The code DoCmd.LockNavigationPane True is used to disable many context menu items:

Tables - Navigation Pane Unlocked

DefaultTableContextMenu
Tables - Navigation Pane Locked

LockedTableContextMenu


However, it does not limit access to the Design View, Import, Export, Copy or Properties menus. For the purposes of the example app, I removed these by hiding various command bar menu items

To do so, I made extensive use of the free Advanced Shortcut Tool add-in by former Access MVP, Dale Fye.

AccessShortcutTool
NOTE:
Dale discussed the use of this excellent tool in an online presentation to the Access Europe User Group on Wed 3 April. A video of that session is now avilable on YouTube.
For more details, see Working with Command bars and the Access Shortcut Tool

The code used is all contained in a function LockNavPane in modSecurity

CODE:

Public Function LockNavPane()

On Error Resume Next

      DoCmd.LockNavigationPane True

      'queries / macros
      With CommandBars("Navigation Pane query or macro Pop-up")
            .Controls("&Open").Visible = False
            .Controls("&Run").Visible = False
            .Controls("&Design View").Visible = False
            .Controls("SQL View").Visible = False
            .Controls("De&lete").Visible = False
            .Controls("&Export").Visible = False
            .Controls("&Copy").Visible = False
            .Controls("O&bject Properties").Visible = False
      End With

      'tables
      With CommandBars("Navigation Pane List Pop-up")
            .Controls("&Open").Visible = False
            .Controls("&Design View").Visible = False
            .Controls("I&mport").Visible = False
            .Controls("De&lete").Visible = False
            .Controls("&Export").Visible = False
            .Controls("&Copy").Visible = False
            .Controls("Ta&ble Properties").Visible = False
      End With

      'modules
      With CommandBars("Navigation Pane Object Pop-up")
            .Controls("&Design View").Visible = False
            .Controls("&Export").Visible = False
            .Controls("&Copy").Visible = False
            .Controls("O&bject Properties").Visible = False
      End With

      'forms / reports
      With CommandBars("Navigation Pane View Pop-up")
            .Controls("&Design View").Visible = False
            .Controls("&Export").Visible = False
            .Controls("&Copy").Visible = False
            .Controls("V&iew Properties").Visible = False
      End With

      With CommandBars("Form View Popup")
            .Controls("La&yout View").Visible = False
            .Controls("&Design View").Visible = False
            .Controls("Cu&t").Visible = False
            .Controls("&Copy").Visible = False
            .Controls("&Paste").Visible = False
      End With

      'form /report title bar - not named so use reference number
      'number may vary depending on Access version / workstation
      With CommandBars(32)
            'this line errors at startup - bypassed using error handling
            .Controls("&Design View").Visible = False
      End With

      With CommandBars(226)
            'this line errors at startup - bypassed using error handling
            .Controls("&Design View").Visible = False
      End With

End Function


This code runs from an Autoexec macro at start up. Similar code UnlockNavPane runs from the Form_Unload event of hidden form frmHide and is used to reverse all these changes immediately before the app is closed

IMPORTANT:
There are several significant issues to working with command bars to disable or remove menu items:

1.   Although most command bars are named, a few do not have a name e.g. the form /report title bar.
      In such cases, I reference the command bar index number supplied by the Advanced Shortcut Tool add-in

2.   The command bar index number may vary depending on the workstation and Access version. Check this carefully.

3.   Command bar names are independent of the Office language used. However, command bar menu item names vary depending on the Office language used.
      The menu item names in the above code will need to be amended for other Office languages such as Spanish.

Overall, there are too many issues for this to be a reliable approach for restricting context menus.

However, there is a much simpler approach which will work reliably. In Access Options, untick Allow Default Shortcut Menus.
Also untick Allow Full Menus to prevent anyone creating new database objects.

AccessOptions
NOTE:
If you want to create an ACCDE file, make sure you do this immediately after applying these changes.
If you close the database first, you will no longer have access to the File...Save As ... ACCDE menu in Backstage view

Many experienced Access users (including hackers) will know how to reverse such changes externally. I do not intend to explain how to do so in this article.

For the purpose of this example app, I apply several of these restrictions at startup using a function ModifyStartupProps run from the Autoexec macro.
Amongst other things, this also disables the Shift bypass

Function ModifyStartUpProps()

'Call this from an autoexec macro or startup form

On Error GoTo Err_Handler

      'Delete existing start up properties
      DeleteStartupProps "AllowFullMenus"
      DeleteStartupProps "StartUpShowStatusBar"
      DeleteStartupProps "AllowBuiltInToolbars"
      DeleteStartupProps "AllowShortcutMenus"
      DeleteStartupProps "AllowToolbarChanges"
      DeleteStartupProps "AllowSpecialKeys"
      DeleteStartupProps "StartUpShowDBWindow"
      DeleteStartupProps "AllowBypassKey"

      'set various properties to False in ACCDB and/or ACCDE files
      StartUpProps "AllowBypassKey", False, True
      StartUpProps "StartUpShowStatusBar", False, True
      StartUpProps "AllowSpecialKeys", False, True
      'next line hides navigation pane
      'StartUpProps "StartUpShowDBWindow", False, True

      If IsACCDE Then
            StartUpProps "AllowFullMenus", False, True
            StartUpProps "AllowBuiltInToolbars", False, True
            StartUpProps "AllowShortcutMenus", False, True
            StartUpProps "AllowToolbarChanges", False, True
      End If

Exit_Handler:
      Exit Function

Err_Handler:
      MsgBox "Error " & Err.Number & " in ModifyStartUpProps procedure : " & Err.Description, vbOKOnly + vbCritical
      Resume Exit_Handler

End Function

'================================
Function IsACCDE() As Boolean

      ' Initiate
      IsACCDE = False

      ' The boolean MDE property exists only in compiled databases (.mde, .accde)
      ' Ignore error (and stay "False") if not present
      On Error Resume Next
      IsACCDE = CurrentDb.Properties("MDE") = "T"

End Function


I have deliberately left sufficient items alone to allow you to unlock the database and examine the code.

You will need to restart the applcation TWICE for any changes to startup restrictions to be implemented.
The first restart will modify the property and this will then take effect when the app is next opened.

Of course, whilst the database is locked, you cannot get access to the VBE to view or modify the code!
However I have provided a 'back-door' using a hidden Autokeys macro

AutokeysMacro
To unlock the database, click Ctrl+Shift+U. This runs a function UnlockApp
To lock the database again, click Ctrl+Shift+L. This runs another function LockApp



Update:   Version 2.5     9 Apr 2024

Following some feedback, I have decided to release an updated version which removes the context menus completely in both ACCDB & ACCDE files.

Click to download:       LockDownDatabaseObjects_v2.5       ACCDB file - approx 3.5 MB (zipped)

Changes made:
1.   Removed functions LockNavPane and UnlockNavPane from modSecurity
2.   Removed LockNavPane from the LockApp function in modSecurity and the Autoexec macro.
3.   Removed UnlockNavPane from the UnlockApp function in modSecurity and the Form_Unload event of frmHide
4.   Added the line DoCmd.LockNavigationPane True to the LockApp function in modSecurity.
      Added DoCmd.LockNavigationPane False to the UnLockApp function in modSecurity

Public Function UnlockApp()
      DoCmd.LockNavigationPane False
      DoCmd.Close acForm, "frmHide"
End Function

'=====================================

Public Function LockApp()
      DoCmd.LockNavigationPane True
      DoCmd.OpenForm "frmHide", , , , , acHidden
End Function


5.   Disabled the If IsACCDE Then and End If lines in ModifyStartUpProps in modSecurity

' to unlock the ACCDB file, enable the If/End If lines below and restart the app TWICE
' to lock the app again, disable these two lines and again restart the app TWICE
If IsACCDE Then ' enable to unlock
      StartUpProps "AllowFullMenus", False, True
      StartUpProps "AllowBuiltInToolbars", False, True
      StartUpProps "AllowShortcutMenus", False, True
      StartUpProps "AllowToolbarChanges", False, True
End If ' enable to unlock


This overcomes all issues related to Office version differences and languages but locking/unlocking the app takes a bit more effort for the developer!

To unlock the app:
a)   Press Ctrl+Shift+U
b)   Open the VBE and navigate to ModifyStartUpProps in modSecurity
      ENABLE the If / End If lines shown above and Save. Restart the app TWICE for the changes to take effect.

      You will then have full access to all context menus for all objects

To lock the app again:
a)   Press Ctrl+Shift+U
b)   Open the VBE and navigate to ModifyStartUpProps in modSecurity
      DISABLE the If / End If lines shown above and Save. Restart the app TWICE for the changes to take effect.

NOTE:
The two keyboard shortcuts will continue to work in ACCDE files and allow access to the VBE
However, as the code will be inaccessible in an ACCDE, end users will not be able to unlock the app

If preferred, you can delete or rename the Autokeys macro before creating an ACCDE file



Video

UPDATE 28 Apr 2024
I have just released a YouTube video (8:20) with a detailed explanation of how this app works.
You can watch the Lock Down Database Objects video on my Isladogs YouTube channel or you can click below:



If you liked the video, please subscribe to my Isladogs on Access channel on YouTube. Thanks.



Summary

This approach is intended to deter most users from unwanted modification of Access objects and data. It is NOT designed to block knowledgeable and determined hackers.

This example app goes well beyond the built-in restrictions provided with ACCDE files.

However, if you want to lock down your application even more, you can apply other more stringent security measures.
See my 3-part article Improve Security in Access Databases



Feedback

Please use the contact form below to let me know whether you found this article interesting/useful or if you have any questions/comments.

Please also consider making a donation towards the costs of maintaining this website. Thank you



Colin Riddington           Mendip Data Systems                 Last Updated 28 Apr 2024



Return to Example Databases Page




Return to Top