My first Dynamics 365 Extension – step by step – eight step

Now we have gotten to Step 4 in the guided path Microsoft offered us on PartnerSource.

Step 4: Provide your offer information

After you have built your app, you will need to define all the attributes that will determine how your app will be listed in Microsoft AppSource. For example, your company information, your offer & plans, marketing information, support contact, and Microsoft AppSource categories.

To define the attributes, visit the Microsoft Azure Publishing Portal.

Refer to the Marketing Validation Guidance and checklist (coming soon) to get insight into the marketing requirements and recommendations.



Lets create a new Madeira offering.

Here I clicked on “Create Dev Center account and join the Azure program”.  This helped me link the development account I created in Step 2 to my Azure publishing.

Next I clicked on “Tell us about your company” and typed away.

Next step to describe my Extension.

Here we need a lot of information.  You can see the asterisk fields that are required.

In the Plan I just created a default plan.  There will be support for more later on.

Marketing, also a generic identifier.

Then go through the language and provide all the marketing information.

Put my name, email and phone in the support page.  In Categories I checked Business Application.  Then finally I requested approval to push to production.

Now I expect to be contacted by Microsoft and helped with getting my Extension online in Dynamics 365 for Financials.

My first Dynamics 365 Extension – step by step – fifth step

Development and installation.

For my development I use source control management.  Soren Klemmensen did a short demo of that setup in his session in NAV TechDays 2016.  We are working on making that solution public in a few months.  In every branch we have a setup file in a json format. That file has all the parameters needed to build an extension.  Here is the one I use for the G/L Source Names project.  When I have this Extension completed I will publish it to my GitHub Account.

  "navVersion": "10.0.14199.0",
  "navProduct": "GLSOURCENAMES",
  "projectName": "NAV2017",
  "baseBranch": "master",
  "uidOffset": "70009200",  
  "versionList": "GLSN10.0",
  "objectProperties": "true",
  "datetimeCulture": "is-IS",
  "appId": "479e77f3-031a-49fe-bb6a-314464c6a9a8",
  "appName": "G/L Source Names",
  "appPublisher": "",
  "appVersion": "",
  "appCompatibilityId": "",
  "appManifestName": "G/L Source Names",
  "appManifestDescription": "G/L Source Names adds the source name to the G/L Entries page.  Source Name is the customer in sales transaction and the vendor in purchase transactions", 
  "appBriefDescription": "Source Names in G/L Entries",
  "appPrivacyStatement": "",
  "appEula": "",
  "appHelp": "",
  "appUrl": "",
  "appIcon": "Logo250x250",  
  		{"id": "G/L-SOURCE NAMES",    "description": "Read G/L Source Names"},
  		{"id": "G/L-SOURCE NAMES, E", "description": "Update G/L Source Names"},
  		{"id": "G/L-SOURCE NAMES, S", "description": "Setup G/L Source Names"}

For every extension we need to make sure that the installation and configuration experience for the customer is easy.  When the Dynamics 365 for Financials user open the Extension Management page our Extension should be visible there.

Here we can see that we need to create images for our Extensions. Later in the process, when we register the Extension on AppSource we will need to supply images in different sizes for out Extension. The image that I used when I created my Extension is 250×250 points. Starting the installation will take the user through an installation wizard. In the installation process the user sees all the properties we add to the Extension manifest definition. I create the manifest with the following code.

$appManifastFilePath = (Join-Path $ExtensionPath "AppManifest.xml")
$appPackageFileName = (Join-Path $ExtensionPath 'AppPackage.navx')

$params = @{ 
  Id = $SetupParameters.appId
  Name = $SetupParameters.appManifestName 
  Publisher = $SetupParameters.appPublisher 
  Version = $SetupParameters.appVersion 
  Description = $SetupParameters.appManifestDescription }
if ($SetupParameters.appBriefDescription -ne "") { $params.Brief = $SetupParameters.appBriefDescription }
if ($SetupParameters.appCompatibilityId -ne "") { $params.CompatibilityId = $SetupParameters.appCompatibilityId }
if ($SetupParameters.appPrivacyStatement -ne "") { $params.PrivacyStatement = $SetupParameters.appPrivacyStatement }
if ($SetupParameters.appEula -ne "") { $params.Eula = $SetupParameters.appEula }
if ($SetupParameters.appHelp -ne "") { $params.Help = $SetupParameters.appHelp }
if ($SetupParameters.appUrl -ne "") { $params.Url = $SetupParameters.appUrl }
if ($SetupParameters.appPrerequisities -ne "") { $params.Prerequisites = $SetupParameters.appPrerequisities }
if ($SetupParameters.appDependencies -ne "") { $params.Dependencies = $SetupParameters.appDependencies }

New-NAVAppManifest @params | New-NAVAppManifestFile -Path $appManifastFilePath -Force

The image and a set of screenshot images are used when creating the Extension package file (navx).

if ($SetupParameters.appIcon -ne "") {  
  $iconPath = (Get-ChildItem -Path $ImagesPath -Filter ($SetupParameters.appIcon + "*")).FullName
} else {
  $iconPath = ""

if (Test-Path $ScreenshotsPath) {
  $screenShots = (Get-ChildItem -Path $ScreenshotsPath).FullName
} else {
  $screenShots = @{}

$params = @{
      Path = $appPackageFileName 
      SourcePath = $ResourceFolder }
if (Test-Path $iconPath) { $params.Logo = $iconPath }
if ($screenShots.Length -gt 0) { $params.ScreenShots = $screenShots }

Get-NAVAppManifest `
  -Path $appManifastFilePath `
  | New-NAVAppPackage @params -Force

In the below screenshots you should be able to see how my parameters are used in the installation process.  I have not yet seen my screenshots used in the Extension installation.

Web links, in the order of appearance are the appUrl, appHelp, appEula and appPrivacyStatement parameters.

Installation done and the user has logged in again and ready to start the Extension setup process.

If the Extension contains any tables then it must also contain permission sets for every table.  From the parameters above you can see that I have three permission sets for my Extension.  One for read permissions, second for update permissions and the third for the Extension setup permissions.  I expect that the user that is installing the Extension has full permissions and is able to assign permissions to other users.

In a simple Extension like this, Extension that does not require any company based setup we still need to make sure that every user has the required permissions to use the Extension.  For this task I use the Assisted Setup feature.

Catch my next blog to read all about that.


My first Dynamics 365 Extension – step by step – fourth step

I got the following response from Microsoft

Hello Gunnar,

We wanted to update you on your request to publish your app, G/L Source Names (Request ID# 835), on Microsoft AppSource. Based on our initial evaluation, your app has been moved to the Microsoft Dynamics NAV AppSource team for further evaluation. You will receive a follow up within 5-7 days or earlier with a status regarding your submission and next steps as relevant.

 Please let us know if you have any questions, or if there is anything we can do to help.

 Where you are in the process:


Request ID# 835

Thank you,
The Microsoft AppSource team

Soon after I got an Excel Template for my object request (microsoft-dynamics-365-for-financials-app-extension-questionnaire-and-object-range-request-form-october-2016).  Here posted for demonstration purposes, don’t use this for your actual process.

I did my object request and for this solution 50 objects is enough.


And this morning I got another email from Microsoft

Hi Gunnar,

50 objects have been assigned to “Kappi ehf.” (PSBC: 6433432) in the range: 70009200-70009249 for your app G/L Source Names.

You have most likely figured out by now that you need to be a Microsoft Partner.  Not a partner, jump to the partner website and sign up.

So, to PartnerSource Business Center to download a new development license.


I like to start by downloading the “Permission Report Detailed (txt)” to verify that my objects are indeed in the license.


After verifying the below lines

Authorized Partner Ranges

Range From     Range To       Object Type                   Permission
70009200       70009249       XMLPort                       RIMDX
70009200       70009249       Query                         RIMDX
70009200       70009249       Form                          RIMDX
70009200       70009249       Dataport                      RIMDX
70009200       70009249       MenuSuite                     RIMDX
70009200       70009249       FieldNo                       RIMDX
70009200       70009249       System                        RIMDX
70009200       70009249       TableDescription              RIMDX
70009200       70009249       Report                        RIMDX
70009200       70009249       TableData                     RIMDX
70009200       70009249       Codeunit                      RIMDX
70009200       70009249       Page                          RIMDX

I can download the license file and start my development process.  That process will be covered in later posts.


My first Dynamics 365 Extension – step by step – third step

I got a response from Microsoft from my first step.

Thank you for submitting your app for consideration to be listed on AppSource.

Once we have had the opportunity to review your app, you will receive a follow up within 1-2 weeks or earlier with a status regarding your submission and next steps as relevant.

Where you are in the process:


Request ID#: 835

Thank you,

The Microsoft AppSource team

This message from Microsoft is an important part of a program, service, or product that you or your company purchased or participate in.

From hereon I get out of sync with the steps on PartnerSource:

Step 3: Build your app

Find more information on how to build an extension in our learning plan on the Dynamics Learning Portal (DLP) (coming soon).

Refer to the Technical Validation Guidelines for Dynamics 365 for Financials (coming soon) to get insight into app technical requirements and recommendations.

To build the app I need to go through many steps.  You are building experience, not a solution.  Therefore we must make sure to have;

  • ToolTip for every field and every action
  • Correct value for ApplicationArea
  • Permission Set(s)
  • Friendly notifications
  • Assisted Setup
  • Help web page(s)
  • Help video(s)

I will go through this list in later blog posts.

Now for the main topic in this post.  Dynamics 365 requires all extension packages to be signed with a code signing certificate.  Microsoft says:

To sign an extension package

To help validate the authenticity of an extension package (the .navx file), we recommend that you have it signed. Code signing is a common practice for many applications. For more information about code signing, see Authenticode and Introduction to Code Signing in the MSDN Library.

  1. To sign an extension package, you need a computer that has the following:
    1. A code signing tool, such as SignTool or CodeSign.SignTool is part of the Windows Software Development Toolkit. For more information, see SignTool.
    2. Microsoft Dynamics NAV 2016 or later.
  2. Obtain a certificate that is enabled for the code signing purpose. You can have certificate as a file or installed in the certificate store of the computer.
  3. It is optional but we recommend that you use a time stamp when signing the .navx file.
  4. Sign the .navx file by using your signing tool.

So, if you want to publish to Microsoft AppSource get your self a valid code signing certificate.  There are number of vendors that can sell a code signing certificate.  Bing delivers this list.

I was allowed to quote one of Microsoft employees:

“I would only suggest using a self-signed certificate for testing and development purposes. If you plan to submit the extension as an app for Dynamics 365 for Financials, you will need to use a certificate from a trusted third party certification authority.

Every version of the extension doesn’t need to be signed using the same certificate. A new version could be signed with a different/new certificate.”

If you don’t already have the SignTool installed you can download it here for windows 7 and 8 and here for windows 10.  On Windows 10 all you need to select in the install process is the Windows Software Developement Kit.


When the installation finishes you will find the SignTool.exe in the folders:

  • x86 -> C:\Program Files (x86)\Windows Kits\10\bin\x86
  • x64 -> C\Program Files (x86)\Windows Kits\10\bin\x64\

When I create the application package (navx file) I check for my code signing certificate and if not found I create one.  Now, of course this is done in PowerShell.

$BaseFolder = (Get-Item $psISE.CurrentFile.FullPath).Directory
. (Join-Path $BaseFolder 'AppPackageSettings.ps1')

Get-NAVAppManifest `
-Path $AppManifestFileName `
| New-NAVAppPackage -Verbose `
-Path $AppPackageFileName `
-SourcePath $ResourceFolder `

if (!(Test-Path -Path $CodeSigningCertificate))
$SecurePassword = ConvertTo-SecureString -String $CodeSigningCertificatePassword -AsPlainText -Force
New-SelfSignedCertificate –Type CodeSigningCert –Subject "CN=ExtensionTest" -CertStoreLocation Cert:\LocalMachine\My
Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -eq "CN=ExtensionTest"} | Export-PfxCertificate -FilePath $CodeSigningCertificate -Password $SecurePassword -Force
Import-PfxCertificate -CertStoreLocation Cert:\LocalMachine\Root -Password $SecurePassword -FilePath $CodeSigningCertificate

& $SigToolExecutable sign /t /f $CodeSigningCertificate /p $CodeSigningCertificatePassword $AppPackageFileName

The first two lines are used to import modules and parameters from the AppPackageSettings file (below).  Lines four to nine create the application package (navx file), Lines eleven to seventeen check if the certificate selected in my AppPackageSettings is present, and if not it will be created in the certificate store and exported to a file.  For this to work this script has be executed in elevated mode (Run as Administrator).

Last line uses the SignTool to sign the application package (navx file).

My AppPackageSettings file looks like this

Set-ExecutionPolicy Unrestricted

Import-Module 'C:\Program Files\Microsoft Dynamics NAV\100\Service\NavAdminTool.ps1' | Out-Null

$NavIde = 'C:\Program Files (x86)\Microsoft Dynamics NAV\100\RoleTailored Client\finsql.exe'
$NavModelTools = 'C:\Program Files (x86)\Microsoft Dynamics NAV\100\RoleTailored Client\NavModelTools.ps1'
. $NavModelTools $NavIde | Out-Null

$ServerInstance = 'DynamicsNAV100'
$Tenants = @('Default')


$AppId = '263f2b5c-4580-41cd-9eea-d1093519adc4'
$AppManifestName = 'GLSourceNames'
$AppManifestPublisher = 'Kappi ehf.'
$AppManifestVersion = ''
$AppManifestDescription = 'G/L Source Names'
$PermissionSets = ('GL SOURCE NAMES')

$AppManifestFileName = (Join-Path $BaseFolder 'AppManifest.xml')
$AppPackageFileName = (Join-Path $BaseFolder 'AppPackage.navx')
$ResourceFolder = (Join-Path $BaseFolder 'Resources')
$SourceName = (Join-Path $BaseFolder 'Original.txt');
$ModifiedName = (Join-Path $BaseFolder 'Modified.txt');
$PermissionSetFilePath = (Join-Path $ResourceFolder 'AppPermissionSet-%1.xml')

$SigToolExecutable = 'C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe'
$CodeSigningCertificate = (Join-Path $BaseFolder 'MyCodeSigningCertificate.pfx')
$CodeSigningCertificatePassword = 'codesignaturepassword'

Don’t worry, I will share the whole script package when the time is right.

When I have the correct code signing certificate I update the two last lines in the settings file and point to my brand new certificate.

In next step we will start coding in C/AL – stay tuned.