On-Premise Extensions & Customer Licenses

On my task list for one of my customers was a nicely isolated module that I could make into an extension.

I’m a huge fan of making many small extensions rather than trying to put all of one customers modifications in one project.

In this case it is a side-by-side project with C/Side so I have created my own app file for the packages. I’ll see if I can blog somewhat about that later.

Extensions are not just for AppSource

Some people seem to think that on-premise we can just as well continue to use C/Side and even though I am a huge C/Side fan I have to disagree.

On-Premise extensions have a lot of value, especially because extensions enforce discipline.

The Caveat

The biggest challenge that I face when programming bespoke Extensions On-Premise is the deployment. Microsoft has made the testing of the license very strickt. In fact, it is more strickt than the runtime check which in my opinion is a bug. Microsoft however has a different opinion. Business Central in fall with the new license model solves it because then, there is no more license.

Temporary Tables

Everyone who has attended my Programming Master Class (800 of you) knows that using Temporary Tables as containers of code are one of the most powerful assets for clean code and reducing code cloning.

The Table behaves as a class with methods and properties and actually replaces the need for Code Units completely. Well, almost.

Using these tables in C/Side is free. It has always been free. End Users only have to pay for tables in their licenses if they write data to the database.

When you ship an extension with a table object that is outside of the customers license you’ll get an error message. The publishing process does not check your code for actual inserts and it probably could not even do that if they wanted to.

In C/Side end-users can import objects with a fob file that are outside of their license.

PowerShell to the Rescue

I’ve created a small PowerShell script that temporarily changes the license at the End-User and later switches it back. There is a lot of clean up to do but for me it was a huge time saver.

My plan is to somehow make this PowerShell script run directly from Visual Studio Code and launch the Windows Client instead of the Web Client.

Please not that I don’t dislike the Web Client but we have some pages in our solution that not yet render perfectly and have to be replaced first with another solution (probably Angular w. DevExpress).

Here is the script.

Don’t expect rocket science. I try to keep my PowerShell understandable.

Set-ExecutionPolicy unrestricted

import-module "C:\Program Files (x86)\Microsoft Dynamics NAV\110\RoleTailored Client\NavModelTools.ps1"
import-module "C:\Program Files\Microsoft Dynamics NAV\110\Service\NavAdminTool.ps1"

$ServiceTier = "2018DEV"
$Version = ""
$xVersion = ""
$AppFolder = "\\DynamicsNAV\Extensions\Performance\Version\"
$AppSource = "\\DynamicsNAV\Extensions\Performance\Source\"
$AppFile = "Mark Brummel_Performance_" + $Version + ".app"
$AppName = "Performance"

#Get-NAVAppInfo -ServerInstance $ServiceTier

Move-Item -Path $AppSource$AppFile -Destination $AppFolder$AppFile -Force -ErrorAction Ignore

Import-NAVServerLicense -LicenseFile "\\License\Development.flf" -ServerInstance $ServiceTier
Restart-NAVServerInstance -ServerInstance $ServiceTier

Uninstall-NAVApp -ServerInstance $ServiceTier -Name $AppName -Version $xVersion
Unpublish-NAVApp -ServerInstance $ServiceTier -Name $AppName
Publish-NAVApp -ServerInstance $ServiceTier -Path "$AppFolder$AppFile" -SkipVerification
Install-NAVApp -ServerInstance $ServiceTier -Name $AppName -Version $Version

Import-NAVServerLicense -LicenseFile "\\License\Customer.flf" -ServerInstance $ServiceTier
Restart-NAVServerInstance -ServerInstance $ServiceTier

#Sync-NAVApp -ServerInstance $ServiceTier -Name $AppName -Mode Clean -Force
#Sync-NAVApp -ServerInstance $ServiceTier -Name $AppName -Mode Add

The bottom two commands are commented out. I use them when I make schema changes to avoid having to create upgrade codeunits during the development process.

The Version and xVersion are because I like to keep some old versions of the .app file while I do the development. The UnInstall and UnPublish is not required if you increase the build number with each build

A tip to Microsoft would be to implement some of the old C/Side code into the Extensions module that only deleted data/colums for those tables/columns that were really changed.

14 thoughts on “On-Premise Extensions & Customer Licenses

      1. Sven Francke

        How can we reach MS to not have that license control when publish apps. Work around is to publish with developer licenses, but you need to restart the service to do the change and kick out everyone from working at the solution. This means that every small updates/ correction has to be done after work day (late), and turns out to not be a familiy friendly job. PS! all objects are in 76.000 serie but still got error.


  1. Arndt

    Hi Mark , you wrote „Business Central in fall with the new license model solves it because then, there is no more license.“
    I don’t know anything about the new license model in fall for on-Prem installation. Please explain the changes.

    Liked by 1 person

    1. Mark Brummel Post author

      The way I understood the new licensing model works for both on-prem and cloud. You just have to move the the new model as far as I understand it.


  2. Dennis Reinecke

    Hey Mark,

    you can also generate a runtimepackage (e.g. in your dev system)
    ‘Get-NAVAppRuntimePackage -ServerInstance $ServerInstance -Id $AppId -ExtensionPath “MyAppToInstall.app”‘
    You can install this file without any license problems


  3. Doug McIntosh

    Hi, Mark!

    Is there any way for an Extension to determine something like the VOICE account #, or some other piece of info that is associated with the customer that “owns” the database, other than pulling something like “Company Name” from the Company Info table?

    This is primarily for AppSource. I am using Stripe to “monetize” our Extensions; but my “Stripe Driver” (Library Extension) creates a “Trial Subscription” and “Stripe Customer” before I have “captured” the end-user’s Billing info. And I would like to be able to store something that “ties” the Stripe Customer (and their subscription(s)) to something even before they enter their Billing info. Is there any way in BC to get that sort of info from AL within an Extension?

    Thanks In Advance!



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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