Application-wide system events (previously known as “Codeunit 1 events”)

You must have heard. Codeunit 1 is a goner! And if you have not heard it – you must have read about it. Because it has been on Microsoft Docks for a while, and also there was a blog that Microsoft spent on it.

Well, before I managed to find these description, I was working on my own overview ;-). So let me share it – I do believe that I look at it from another angle.

Where are my events?

If we want to extend codeunit 1, we have been subscribing to events. And if not – you should have ;-). So, first question would be – where are the events that we were subscribing to??

Well, I made my own overview of all the published events in codeunit 1, and the mapping to the new event in the table below:

OnCheckPreconditionsPerCompany Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnCheckPreconditionsPerCompany>
OnCheckPreconditionsPerDatabase Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnCheckPreconditionsPerDatabase>
OnInstallAppPerCompany NOT AVAILABLE ANYMORE
OnInstallAppPerDatabase NOT AVAILABLE ANYMORE
OnUpgradePerCompany Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnUpgradePerCompany>
OnUpgradePerDatabase Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnUpgradePerDatabase>
OnValidateUpgradePerCompany Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnValidateUpgradePerCompany>
OnValidateUpgradePerDatabase Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnValidateUpgradePerDatabase>
OnAfterAutoFormatTranslate Codeunit<AutoFormatManagement>.PROCEDURE<OnAfterAutoFormatTranslate>
OnAfterCaptionClassTranslate Codeunit<CaptionManagement>.PROCEDURE<OnAfterCaptionClassTranslate>
OnAfterCompanyClose Codeunit<LogInManagement>.PROCEDURE<OnAfterCompanyClose>
OnAfterCompanyOpen Codeunit<LogInManagement>.PROCEDURE<OnAfterCompanyOpen>
OnAfterFindPrinter Codeunit<ReportManagement>.PROCEDURE<OnAfterGetPrinterName>
OnAfterGetApplicationVersion Codeunit<Application System Constants>.PROCEDURE<OnAfterGetApplicationVersion>
OnAfterGetDatabaseTableTriggerSetup Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterGetDatabaseTableTriggerSetup>
OnAfterGetDefaultRoleCenter Codeunit<Conf./Personalization Mgt.>.PROCEDURE<OnAfterGetDefaultRoleCenter>
OnAfterGetGlobalTableTriggerMask Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterGetGlobalTableTriggerMask>
OnAfterGetSystemIndicator Table<Company Information>.PROCEDURE<OnAfterGetSystemIndicator>
OnAfterHasCustomLayout Codeunit<ReportManagement>.PROCEDURE<OnAfterHasCustomLayout>
OnAfterMakeCodeFilter NOT AVAILABLE ANYMORE
OnAfterMakeDateFilter Codeunit<TextManagement>.PROCEDURE<OnAfterMakeDateFilter>
OnAfterMakeDateText NOT AVAILABLE ANYMORE
OnAfterMakeDateTimeFilter Codeunit<TextManagement>.PROCEDURE<OnAfterMakeDateTimeFilter>
OnAfterMakeText NOT AVAILABLE ANYMORE
OnAfterMakeTextFilter Codeunit<TextManagement>.PROCEDURE<OnAfterMakeTextFilter>
OnAfterMakeTimeFilter Codeunit<TextManagement>.PROCEDURE<OnAfterMakeTimeFilter>
OnAfterMakeTimeText NOT AVAILABLE ANYMORE
OnAfterOnDatabaseDelete Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnDatabaseDelete>
OnAfterOnDatabaseInsert Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnDatabaseInsert>
OnAfterOnDatabaseModify Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnDatabaseModify>
OnAfterOnDatabaseRename Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnDatabaseRename>
OnAfterOnGlobalDelete Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnGlobalDelete>
OnAfterOnGlobalInsert Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnGlobalInsert>
OnAfterOnGlobalModify Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnGlobalModify>
OnAfterOnGlobalRename Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnGlobalRename>
OnAfterReportGetCustomRdlc Table<Custom Report Layout>.PROCEDURE<OnAfterReportGetCustomRdlc>
OnBeforeCompanyClose Codeunit<LogInManagement>.PROCEDURE<OnBeforeCompanyClose>
OnBeforeCompanyOpen Codeunit<LogInManagement>.PROCEDURE<OnBeforeCompanyOpen>
OnBeforeOnDatabaseDelete Codeunit<GlobalTriggerManagement>.PROCEDURE<OnBeforeOnDatabaseDelete>
OnBeforeOnDatabaseInsert Codeunit<GlobalTriggerManagement>.PROCEDURE<OnBeforeOnDatabaseInsert>
OnBeforeOnDatabaseModify Codeunit<GlobalTriggerManagement>.PROCEDURE<OnBeforeOnDatabaseModify>
OnBeforeOnDatabaseRename Codeunit<GlobalTriggerManagement>.PROCEDURE<OnBeforeOnDatabaseRename>
OnBeforeOpenSettings Codeunit<Conf./Personalization Mgt.>.PROCEDURE<OnBeforeOpenSettings>
OnEditInExcel Codeunit<ODataUtility>.PROCEDURE<OnEditInExcel>
OnRoleCenterOpen Codeunit<Conf./Personalization Mgt.>.PROCEDURE<OnRoleCenterOpen>

I indicated in red the ones that need a bit attention, as either they are not available, or are renamed.. .

Are there new events as well?

Yes! And quite many of them. I just don’t know how I can give you a complete overview of all the events “that could have been in codeunit 1, but are now spread over multiple codeunits.. “. So, let me just give you a few tips of where you could find such “generic” or “platform wide” or “…” events.

In my opinion, the below codeunits have these kind of events that I think are very interesting in a application-wide-context:

  • LogInManagement
  • ReportManagement
  • Application System Constants
  • Conf./Personalization Mgt.
  • TextManagement
  • AutoFormatManagement
  • CaptionManagement
  • GlobalTriggerManagement
  • SaaS Log In Management
  • Company Information
  • Custom Report Layout
  • ODataUtility
  • Data Upgrade Mgt.

So. Just to help you … I created another list with events which I think are quite interesting for you. In bold, you see the ones that didn’t exist in Codeunit 1.

  • Codeunit<LogInManagement>.PROCEDURE<OnAfterCompanyClose>
  • Codeunit<LogInManagement>.PROCEDURE<OnAfterCompanyOpen>
  • Codeunit<LogInManagement>.PROCEDURE<OnAfterLogInEnd>
  • Codeunit<LogInManagement>.PROCEDURE<OnAfterLogInStart>
  • Codeunit<LogInManagement>.PROCEDURE<OnBeforeCompanyClose>
  • Codeunit<LogInManagement>.PROCEDURE<OnBeforeCompanyOpen>
  • Codeunit<ReportManagement>.PROCEDURE<OnAfterGetPaperTrayForReport>
  • Codeunit<ReportManagement>.PROCEDURE<OnAfterGetPrinterName>
  • Codeunit<ReportManagement>.PROCEDURE<OnAfterHasCustomLayout>
  • Codeunit<ReportManagement>.PROCEDURE<OnAfterSubstituteReport>
  • Codeunit<Application System Constants>.PROCEDURE<OnAfterGetApplicationVersion>
  • Codeunit<Conf./Personalization Mgt.>.PROCEDURE<OnAfterCopyProfile>
  • Codeunit<Conf./Personalization Mgt.>.PROCEDURE<OnAfterGetDefaultRoleCenter>
  • Codeunit<Conf./Personalization Mgt.>.PROCEDURE<OnBeforeOpenSettings>
  • Codeunit<Conf./Personalization Mgt.>.PROCEDURE<OnGetBuiltInRoleCenterFilter>
  • Codeunit<Conf./Personalization Mgt.>.PROCEDURE<OnInitializeProfiles>
  • Codeunit<Conf./Personalization Mgt.>.PROCEDURE<OnProfileChanged>
  • Codeunit<Conf./Personalization Mgt.>.PROCEDURE<OnRoleCenterOpen>
  • Codeunit<TextManagement>.PROCEDURE<OnAfterMakeDateFilter>
  • Codeunit<TextManagement>.PROCEDURE<OnAfterMakeDateTimeFilter>
  • Codeunit<TextManagement>.PROCEDURE<OnAfterMakeTextFilter>
  • Codeunit<TextManagement>.PROCEDURE<OnAfterMakeTimeFilter>
  • Codeunit<TextManagement>.PROCEDURE<OnBeforeMakeTextFilter>
  • Codeunit<AutoFormatManagement>.PROCEDURE<OnAfterAutoFormatTranslate>
  • Codeunit<CaptionManagement>.PROCEDURE<OnAfterCaptionClassTranslate>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterGetDatabaseTableTriggerSetup>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterGetGlobalTableTriggerMask>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnDatabaseDelete>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnDatabaseInsert>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnDatabaseModify>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnDatabaseRename>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnGlobalDelete>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnGlobalInsert>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnGlobalModify>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnAfterOnGlobalRename>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnBeforeOnDatabaseDelete>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnBeforeOnDatabaseInsert>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnBeforeOnDatabaseModify>
  • Codeunit<GlobalTriggerManagement>.PROCEDURE<OnBeforeOnDatabaseRename>
  • Codeunit<SaaS Log In Management>.PROCEDURE<OnSuppressApprovalForTrial>
  • Table<Company Information>.PROCEDURE<OnAfterGetSystemIndicator>
  • Table<Custom Report Layout>.PROCEDURE<OnAfterReportGetCustomRdlc>
  • Codeunit<ODataUtility>.PROCEDURE<OnEditInExcel>
  • Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnCheckPreconditionsPerCompany>
  • Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnCheckPreconditionsPerDatabase>
  • Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnIsUpgradeInProgress>
  • Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnUpgradePerCompany>
  • Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnUpgradePerDatabase>
  • Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnValidateUpgradePerCompany>
  • Codeunit<Data Upgrade Mgt.>.PROCEDURE<OnValidateUpgradePerDatabase>

But that’s not all…

If you look for example into Codeunit “LoginManagement”, you’ll see that it subscribes to an event called “OnCompanyClose”, which is an event in codeunit “2000000003”.

I wasn’t able to export that codeunit (with powershell, nor with the classic client) – and even found a few more like those codeunits. In classic environment, this is what I saw:

So all these codeunits end with “Triggers” – which means in VSCode, we are able to access them with Intellisense like:

Here is an overview of all the events in these “system trigger codeunits”:

Company Triggers OnCompanyClose
Company Triggers OnCompanyOpen
Debugger Triggers OnDebuggerBreak
Extension Triggers OnInstallAppPerCompany
Extension Triggers OnInstallAppPerDatabase
Global Triggers GetDatabaseTableTriggerSetup
Global Triggers GetGlobalTableTriggerMask
Global Triggers OnDatabaseDelete
Global Triggers OnDatabaseDelete
Global Triggers OnDatabaseInsert
Global Triggers OnDatabaseModify
Global Triggers OnDatabaseRename
Global Triggers OnGlobalDelete
Global Triggers OnGlobalInsert
Global Triggers OnGlobalModify
Global Triggers OnGlobalRename
Upgrade Triggers OnCheckPreconditionsPerCompany
Upgrade Triggers OnCheckPreconditionsPerDatabase
Upgrade Triggers OnUpgradePerCompany
Upgrade Triggers OnUpgradePerDatabase
Upgrade Triggers OnValidateUpgradePerCompany
Upgrade Triggers OnValidateUpgradePerDatabase
Version Triggers GetApplicationBuild
Version Triggers GetApplicationVersion
Version Triggers GetReleaseVersion
Reporting Triggers GetPaperTrayForReport
Reporting Triggers GetPrinterName
Reporting Triggers HasCustomLayout
Reporting Triggers MergeDocument
Reporting Triggers ReportGetCustomRdlc
Reporting Triggers ScheduleReport
Reporting Triggers SubstituteReport
UI Helper Triggers AutoFormatTranslate
UI Helper Triggers CaptionClassTranslate
UI Helper Triggers GetApplicationLanguage
UI Helper Triggers GetCueStyle
UI Helper Triggers GetDefaultRoundingPrecision
UI Helper Triggers GetSystemIndicator
Filter Helper Triggers MakeCodeFilter
Filter Helper Triggers MakeDateFilter
Filter Helper Triggers MakeDateTimeFilter
Filter Helper Triggers MakeIntFilter
Filter Helper Triggers MakeTextFilter
Filter Helper Triggers MakeTimeFilter
System Action Triggers CustomizeChart
System Action Triggers GetDefaultRoleCenterID
System Action Triggers InvokeExtensionInstallation
System Action Triggers OnEditInExcel
System Action Triggers OpenContactMSSales
System Action Triggers OpenDebugger
System Action Triggers OpenSettings

I’m not sure in how to use all of them – but it is a great help to simply look into the code of Busines Central, as most (if not all) of these events exist because Microsoft needed them. You can figure out how to use them, and in many cases, you’ll find what are the actual events you should use as a developer.

Enjoy!

5.00 avg. rating (98% score) - 3 votes

Permanent link to this article: https://www.waldo.be/2018/10/23/application-wide-system-events-previously-known-as-codeunit-1-events/

9 comments

Skip to comment form

    • Stephan Weidmann on October 23, 2018 at 6:19 am
    • Reply

    you can c&p the System codeunits to peek into it. Just stand on an object you have Access (Luke cu 50000)

      • waldo on October 23, 2018 at 10:37 am
        Author

      Thanks, but I’m not sure what you mean…

    • bert van gestel on October 23, 2018 at 12:35 pm
    • Reply

    I would like an event that triggers on each error a users gets. Including user name and business application stack trace. That would give so much info on the users experience. IF users need training, if a part of the application is to difficult, …

      • waldo on October 23, 2018 at 1:19 pm
        Author

      Absolutely.
      Now, I’ve seen something like that in the “Admin center” they are creating for CSP-partners for SaaS implementations. Let’s see if we can get this for OnPrem…

  1. What Stephan meant:

    Go to Object Designer, Codeunit 2000000002 “Global Triggers” (as an example). Select that line and copy into clipboard.
    Then go to any existing 50000..99999 object in the object designer and “Paste” the object from your clipboard.
    Ignore the error, assign a new number and a new name.
    Now you can check the code inside the codeunit you just “created”.

    • Gerd Hübner on February 10, 2019 at 4:20 pm
    • Reply

    @Thomas
    … at least this works up to the December build …

    For those, who wonder why the new trigger codeunits in the range 2000000001 to 2000000010 are the only objects not readable with a developer license… – they might simply have missed them.

    • Nikola Kukrika on March 1, 2019 at 11:01 am
    • Reply

    There is an article published under official upgrade documentation. We have presented this at Directions – you have missed the great session ;-).
    https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/upgrade/transition-from-codeunit1

    There is also a replacement COD1 that you can use for upgrade. We do not recommend to use this one in production, since it is not maintained. We support the code only foar upgrade.

      • waldo on March 1, 2019 at 11:21 am
        Author

      Thank, Nikola! Great additional info!

      • waldo on March 1, 2019 at 1:14 pm
        Author

      And in my defence, that link is on the very beginning of my blogpost :p

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.