Preamble
Soon after starting to work with Business Central, users discover the hierarchical structure of how Microsoft flagship ERP system is designed. They soon hear about the stacked Microsoft extensions System, System Application, Base application, followed by other Microsoft and ISV’s solutions installed in the user’s environment. Almost all extensions the system is based upon are visible in the Extension Management page. However, some of the installed extensions in the online Business Central are not visible in the Extension Management page. In this blog post I will share my method of discovering hidden extensions in Business Central and exposing the objects behind them.
At the end of the blog post I will attempt to create my own hidden extension in Business Central.
Discover hidden extensions in Business Central
Let’s start by looking at the Page Inspection on Extension Management page:
We can see that the Filter is set to exclude extensions whose Name is not matching the mask ‘_Exclude_*’.
Who are these extensions “_Exclude_*” ?
To get the answer let’s download the artifacts for a specific version of Business Central.
How do we actually know what was published by Microsoft?
If you are not familiar with BCContainerHelper powershell module and artifacts please read Freddy’s article.
Or, if you didn’t create your own container using BCContainerHelper, give my previous article a read!
Open Powershell and download the artifacts for the version of BC of your choice:
Download-Artifacts -artifactUrl (Get-BCArtifactUrl) -includePlatform
In my folder C:\bcartifacts.cache\sandbox\20.2.41144.42781\w1\Extensions
there is a file: AppInfo.financials.json that contains all extensions installed – much more than is visible through the Page Extensions page:
When you open the file above you will notice that some of these extensions are prefixed with the word “__Exclude”.
And if we attempt to find these extensions in Business Central, indeed, these extensions are not visible in the Extension Management page:

Discover content of hidden extensions
Albeit we uncovered these hidden extensions, let’s continue and discover the hidden content of these extensions and where their objects are used.
Aren’t you curious what is inside each app file?
If yes, download 7-zip and rename the *.app to *.7z and extract the new 7z file. You will get access to all the objects inside the exclude extension.
UI Example: discover hidden extensions in Business Central, focus on an “__Extended …” apps
If we open Customer List and launch the view “Customer Ship To Addresses”.

First, we need to find out what is the object behind the page:

Launching the Page Inspection we notice that the “Customer Ship To Addresses” is a query with ID = 2450.
Let’s start searching for the extension containing the query
In the Page Inspection, under Extensions, there is no extension:

Therefore, let’s try to turn a few more stones.
Obvious places
I tried finding it in the Base Application:

So, the query is not in Base Application. Where else could we look into?
Let’s turn a few more stones … we can look in the other extensions, System, System Application and Application.
Again, we can’t find it in any of these extensions. Ultimately, let’s try it online.
Ultimately, change all “Exclude” app files and rename the extension to “7z”. Then unzip them. At some point you will unzip the Dynamics 365 Smartlist exclude file. That’s when you’re going to find the query 2450.
Or look ahead …
Online
Navigate to AL APP Extensions on github and Search for Query 2450:

Bingo! If we open the Smartlists folder we can see the extension’s app.json file:

Zooming in hidden content
To check all objects in the hidden extension we can add it in our project in app.json to our dependencies and download the symbols:

After download we can see all objects in this extension:

Lastly, we can see the query source code:

Can AL developers not only discover hidden extensions, but also create their own hidden clusters of code?
It is possible. Though, it’s not all hidden, and … I don’t know if it is really a good thing.
The secret ingredient is to name your extension “_Exclude …” as seen in my app.json:
{
"id": "02de53f5-7a38-45ca-9343-d04d9c3a7639",
"name": "_Exclude_SilviuExt",
"publisher": "Default publisher",
"version": "1.0.0.0",
"brief": "",
"description": "",
...
}
Furthermore, to see it in action, I created an action on “Customer List” page and I triggered the new action. The result: a page included in the hidden extension.
Hidden Table:
table 60100 SampleTable
{
DataClassification = CustomerContent;
fields
{
field(1; "Entry No."; Integer)
{
DataClassification = SystemMetadata;
}
field(2; Description; Blob)
{
DataClassification = SystemMetadata;
}
}
keys
{
key(Key1; "Entry No.")
{
Clustered = true;
}
}
}
Hidden page:
page 60100 SamplePage
{
ApplicationArea = All;
Caption = 'SamplePage';
PageType = List;
SourceTable = SampleTable;
layout
{
area(content)
{
repeater(General)
{
field("Entry No."; Rec."Entry No.")
{
ToolTip = 'Specifies the value of the Entry No. field.';
}
field(Description; Rec.Description)
{
ToolTip = 'Specifies the value of the Description field.';
}
}
}
}
}
Action trigger on customer List:
pageextension 60100 HiddenHelloWorld extends "Customer List"
{
layout
{
// Add changes to page layout here
}
actions
{
// Add changes to page actions here
addafter(ApplyTemplate)
{
action(ShowHiddenPage)
{
ApplicationArea = All;
Caption = 'Show Hidden Page';
trigger OnAction()
begin
Page.Run(60100);
end;
}
}
}
}
Page Inspection details for our hidden object:
- fields display our extension name
- Extensions group does not display details of our new extension
Likewise, Extension Management page does not display our extension.
Conclusions
In this blog post I demonstrated that there are more extensions than what we see reported in the Extension Management page. Moreover, based on a simple use case, I shared how we can not only discover Business Central hidden extension, but also showed how we can uncover the source code of the objects behind hidden extension. Lastly, we investigated if it is even possible for us to create hidden extensions, and. as a result, I created a hidden extension.
At the same time, there could be other ways of uncovering hidden extensions and I encourage readers to share their experience of discovering where an actual piece of UI is hidden.
Hope this helps!