In the first part, I explained how to request to list an app in AppSource, how to get a developer account and how to generate the offer in the AppSource publishing portal. If you have not had a chance to read it, you can find it here. If you missed the second part, which described the considerations and added functionality to make your extension well rounded, you can find it here.
This will be the last part of this little miniseries, unless you bring up so many questions that I might combine them into another blog – challenge me. I am going to explain this time the packaging process and what comes after. While it is fairly simple, it is still important that you pay attention to it.
Obviously, you need your developed code and you also need the base NAV version that you developed your code on. This is required, because extensions are only “delta files”, which describe the changes that your extension makes and the system implements those changes when the extension is published and installed.
You also need some additional things. You must install the development PowerShell commandlets, which automatically get installed, when you install the development environment. You need a code signing certificate, since you do have to sign the extension. And you need the tool to sign the extension.
A code signing certificate validates that the code is unaltered after you packaged it and that you are the author. They can be purchased from GoDaddy, Verisign, DigiCert, or other companies. I am not going to explain now to go through the purchasing process, since it can vary based on where you get it from. However, there are some things that are always the same.
First, you need a Certificate Signing Request, which can be generated through the Internet Information Services Manager, for instance. Based on your specific requirements and tools available, the procedures are a bit different, but GoDaddy actually has a pretty decent description how to create one on a Windows computer. You can find it here. You will notice that you need to create the request on the computer you will use to sign the extensions. I have seen it also work on different computers, but I still would follow the recommendation.
It is very important that you make the private key exportable, since you will need this to convert your certificate into a PFX file, if your certificate provider doesn’t provide it in this format already.
Once the certificate signing request is created, you follow the steps of your provider. You might have to verify some information with them during that process to validate that you are who you say you are. Once you have your certificate, download it. Regardless of your provider, the steps to create a PFX file out of it, are the same. You can follow this article, start with “Install your certificate in MMC”.
The tool to sign your extension is called SignTool (clear and precise name for a change). You can find instructions on how to download and even use it on the SignTool page in MSDN. It also describes the different parameters of this tool, but I am going to show you later what you need.
You will need the delta file for your extension. Although you might know that already, I am going to show you later how to create those.
You will also need a fully functioning permission set that must be setup to use your extension. This can be setup in NAV and then exported. More to that later as well.
In the first post, I said that you need at least one screenshot that will be included in AppSource. You should also include the screenshot (or multiple) in your extension. To make it easier, just use the same. At the same time, I also mentioned that you need a logo for the app. This could be your company logo or actually a custom designed logo for your extension, it should be 200×200 pixels for the version that you should include in your extension package.
The last pieces of information you need are:
Let’s get started in creating the package.
To create the delta file, you need to have the base version of NAV and your customized objects as text format. I would export the stock NAV objects as text and save them in a general location, so you can reuse those. It is not necessary to use the latest cumulative updates for your development, so you can create this extension and all future versions on the RTM release and keep the source code out there.
Once you are done with the development of your extension, you need to export all objects as text. This is the easiest. If you only export your modified objects as text, you still need to copy the stock NAV objects. I usually just export them from the development environment (select all and then export) and save them somewhere in a temp folder.
While it is not really necessary, it is easier for source code management as well as merges in the future, if you have each object in its own file. So, you will need to do this for stock NAV and your extension. Open up the Development PowerShell window and use the following code to create the individual object files.
Split-NAVApplicationObjectFile -Source [exported stock NAV objects file] -Target [Folder to store individual files] [-PreserveFormatting] [-Force]Split-NAVApplicationObjectFile -Source [exported customization object file] –Target [Folder to store individual files for customization] [-PreserveFormatting] [-Force]
The target folders do not need to exist; they will be created then. You do not need the “PreserveFormatting” parameter, it just makes sure that the source code is not reformatted when split into separate files. If you omit the “Force” parameter, you will be asked, if you want to overwrite the files, if they exist already in the target folder.
Now that you have the objects in their separate files, you can create the delta file using the following PowerShell command:
Compare-NAVApplicationObject -OriginalPath [Folder for stock objects] -ModifiedPath [Folder for customization] -DeltaPath [path to store delta and other packaging files] [-Force]
The “Force” parameter is not needed, you then will be asked, if you want to overwrite the delta file, if it already exists. There are two additional parameters, which are not needed. The parameters are “Legacy” and “NoCodeCompression”. Do never use “Legacy”, even the help of the commandlet tells you that. “NoCodeCompression” only creates a larger file, but not needed.
If you have all other information as listed above, you are now ready to create the App manifest and then package the extension.
The extension needs to provide the proper permissions to users, so that the extension functions. You cannot rely on the users all being setup with “SUPER” rights. You can go as detailed as you want with permission sets, but you might want to limit it to one or two permission sets. One permission set should contain the proper rights to setup the extension and one should contain the proper rights to use the extension.
Once the permissions are setup and tested (this is important), you can export the permissions also via PowerShell. Please make sure that you test your extension with a user that has only the following permission sets:
When you have your extension installed, but not setup yet, the user with the above permissions still should be able to process any transaction normally, no errors should happen that are due to permissions to your extension. Once you have tested this, please add your permission set(s), setup your extension, and test again. It should work and not throw errors due to permissions.
After this test, please remove the permissions again, and then test again. This also should work again, but this time, it should properly generate any data that is needed for your extension, but you should not be able to directly execute any extension functionality.
The export of the permission set(s) is very easy. It’s PowerShell again:
Export-NAVAppPermissionSet -PermissionSetId [ID] -Path [path to your package files\permissionset.xml] – ServerInstance [instance of the server with your extension]
You can export multiple permission sets, you then have to combine those files. Open all permission files and then copy the “<PermissionSet>” nodes from one into the other after the last “</PermissionSet>” element.
In addition to the permission sets, which are required, you can also export report layouts, in case your reports include multiple layouts and you want to provide them for your users.
Export-NAVAppReportLayout -LayoutCode [code] -Tenant [default|tenant] -Path [path to the package directory\[code].xml] -ServerInstance [instance]
The “Code” is the unique identifier of the layout code. Usually, you will develop in a single tenant environment, so you don’t need the “Tenant” parameter. If you developed in a multitenant environment, you would need this.
If you want to setup tables of your extension, for instance, with standard default values, you will have to export that data. But you also have to make sure that you handle this properly in the upgrade code within your extension.
Export-NAVAppTableData -Tenant [default|tenant] -Path [path to package directory\T[ID].data] -TableId [ID] -ServerInstance [instance]
If you have not created the app manifest for this extension before, you will need to create one first:
New-NAVAppManifest -Name [extension name] -Publisher [publisher] -Brief [brief description] -Description [description] -Version [version number] -CompatibilityId [id] -PrivacyStatement [privacy url] -Eula [EULA url] -Help [help url] -Url [support url] -Dependencies [dependencies] | New-NAVAppManifestFile -Path [path to manifest]
This will create a new NAV extension manifest and save it in “Path to Manifest”. The extension name and publisher have to match what was defined in AppSource and in the Dev Center as described before. The “Version” should start with 18.104.22.168 and you should increment it by 0.0.0.1 every time you build a new one. The first two numbers can be incremented when you add features, basically. If there are any significant changes, which would make the new version not work, if at least one specific version was installed previously, the “CompatibilityId” should be set to the minimum version that should have been installed before. You should never really use that, since you should handle all data structure changes in the code properly.
If you had a manifest file before, just open it with a text editor and update the version number. This is easier than using the PowerShell commands, but you can also do that:
Get-NAVAppManifest -Path [path to the manifest file] | Set-NAVAppManfiest -Version [new version] -CompatibilityId [if changed] | New-NAVAppManifestFile -Path [path to the manifest file] -Force
Once you have the manifest and you have updated the version number correctly, you will have to package the extension. For this, we have to go back to PowerShell:
Get-NAVAppManifest -Path [path to the manifest file] | New-NAVAppPackage -Path [path to the package file] -SourcePath [path to package files] -Logo [path to logo file] -ScreenShots [path to folder with screenshots] -Force
The PowerShell commands first get the manifest file and then create a new package. The “SourcePath” is the path to a folder with the permissions (see above), the delta file, and possible other files. Once the file is created, you need to sign the package file with the code signing certificate that you created earlier. The sign tool is located in “C:\Program Files (x86)\Windows Kits\8.0\bin\x64”.
Signtool.exe sign /f [certificate file] /p [Password for certificate] /t http://timestamp.verisign.com/scripts/timestamp.dll [extension file]
The “/t” parameter adds a timestamp to the signed extension. This is important so that the extension still looks valid, even if the certificate expired.
Technically, you are ready to go to the publishing portal, upload your navx file, and submit it. But wait a minute: There is one small thing that I would recommend to you: One more round of testing…
Create a new server instance with a stock NAV database. I would also suggest to create a web server instance, so that you can test it via the web client – this is the same way that the validation team will test. Publish your extension, but do not install it. This you will do through the Extension Management screen, the same way that the validation team and the D365 users will do it.
Create two users in the environment. One user is the admin user and should have “SUPER” assigned as the permission set. The second user should only have the roles “D365 FULL ACCESS” and “LOCAL” assigned. This is the same way that the regular users are setup in D365. Then go to the “Application Area” screen and make sure that “Basic” and “Suite” are checked, but only those. You will have to log out and log back in.
Make sure that you are logged in with the normal user and test the system. You shouldn’t get any errors and everything should work normally. Then log in as the admin user and go to “Extension Management” and install your extension, but do not set it up or give the users permissions. You should be able to install without errors.
Switch back to the normal user and test again the same processes (based on your key usage scenario document). You still should be able to run everything without errors and your extension should not do anything. Then assign this user the extension permission set and configure the extension. Retest again and make sure that you can do all processes, your extension works, and you do not get errors.
Log in as the admin user and uninstall the extension. You will have to validate that the extension is uninstalled without an issue and that the data created is gone.
Now you can submit everything to the Microsoft team via the publishing portal.