Find Out if an Extension is Installed

EDIT: I’ve just been informed that users will not have access to the “NAV App Installed App” system table in the near future, so while the following will work for a typical NAV 2017 installation, it will not work for a Dynamics 365 extension.

EDIT2: I’ve posted a much better solution here!!

Having already created and published one extension, I am now in the process of creating a second extension, and in some cases, I want my extensions to act differently depending on if the other extension is installed or not. I could easily make each extension dependent on each other so that I know they’re always both installed, but where’s the fun in that!!??

You can do this by using the NAV App Installed App system table (2000000153). This table lists all of the extensions that are installed within the tenant.

Now, before I go further, I will mention that there is a function named IsInstalled in Codeunit 2500 (NavExtensionInstallationMgmt) that you could call, but this function accepts a Package ID, which is different than the Application ID of the extension. I prefer to use the Application ID, as I am in control of what that value is through the extension packaging process, and I like that control. So……because of this, I am not going to use the built-in function.

Here’s what you need to do:

First, create a local function that returns true/false depending on if a given Application ID is installed or not.

LOCAL CheckIfExtensionInstalled(AppID : GUID) : Boolean
EXIT(NAVAppInstalledApp.GET(AppID));

Next, we need to write local functions to return our extension Application IDs. You can get the GUID from the extension manifest file when you build the NAVX file. Repeat this process and create a function for each extension that you want to see if it’s installed.

LOCAL GetExtension1AppID() : GUID
//-- AppID: GUID
EVALUATE(AppID,'e7deb9a9-6727-4157-838e-bcf4a0853942');
EXIT(AppID);

Finally…….create a global function that will check for each extension. We will call this function from throughout our application wherever we need our application to act accordingly.

Extension1IsInstalled() : Boolean
EXIT(CheckIfExtensionInstalled(GetExtension1AppID));

Now, all we need to do is use the functionality in our code, such as the following example:

IF Extension1IsInstalled THEN BEGIN
  //-- do something
END ELSE BEGIN
  //-- do something else
END;

One thing to note, you will probably also need to give your codeunit (or whatever object you added the above functions to) permissions to read the NAV App Installed App table as the average user does not typically have this permission.

Rebrand your Web Client

If you are working with Dynamics 365 for Financials, when it comes time to submitting your extension to AppSource, you need to supply some marketing materials, for examples walkthroughs and videos.

As the only option right now is to use the Dynamics NAV 2017 Web Client for testing (no Dynamics 365 sandbox…yet!), it can be a pain that the title ribbon in the Web Client says Dynamics NAV. When submitting to AppSource, there can be no trace of NAV in any of your marketing materials.

But with a small change to your Web Client url, you can change that title ribbon from this…

navribbon

to this…

d365ribbon

You do this by simply adding the following parameter to the end of the url:

?aid=fin

Example:

http://localhost:8080/DynamicsNAV100/WebClient/?aid=fin

That’s it! Bookmark both versions of the url to easily switch between a NAV demo and a Dynamics 365 demo!

Determining the right client

In certain scenarios, it may be important to know what client that the user is working in. Perhaps you have an action that doesn’t work in the Web Client, or maybe you have some code that interacts with a device camera that only works in the Device Client. Or maybe you want to send a link to your users that allows them to open a record, and we want to make sure the link is for the correct client?

First, I want to be clear that what I am describing here is based on the Dynamics NAV 2017 platform. Yes, this means the Dynamics 365 for Financials platform falls under this umbrella as well. Perhaps bits and pieces are supported on older platforms, but my intention is to never look backwards and keep this train moving forward!

Now to it…

There are some system variables that we need to get familiar with:

  • CLIENTTYPE
    • an option variable that contains the various client types:
      • Windows
      • Web
      • SOAP
      • OData
      • NAS
      • Background
      • Management
      • Tablet
      • Phone
      • Desktop
      • ODataV4
  • CURRENTCLIENTTYPE
    • Returns the client type that is currently executing the code.
  • DEFAULTCLIENTTYPE
    • Returns the default client type, as defined in the Dynamics NAV Server configuration. For more information click here.

Example 1: Show an action only in the Windows Client.

  • In the Development Environment, design the page that contains the action.
  • Make sure that the action does something. If it does not do anything, then it will always be hidden. For testing purposes you can add the following code to the onAction trigger for the action:
MESSAGE('A message for testing');
  • Add a global Boolean variable named ‘showMyAction’:

globalvariable

  • Assign the global variable to the Visible property of the action that you wish to conditional show/hide (you can show this property as a column in the Action Designer now!!):

actiondesigner

  • Add the following code to the onOpenPage trigger:
showMyAction := CURRENTCLIENTTYPE = CLIENTTYPE::Windows;
  • Close, save and compile your page.
  • If you run the page in the Web Client for example, you will not see the action on the ribbon of the page. Running the page from the Windows Client will show the action.

Example 2: Create a url that takes a user to the first customer record.

  • In the Development Environment, create a new codeunit.
  • In the onRun trigger, create the following local variables:

capture-globalvariables

  • In the onRun trigger, add the following code:
Customer.FINDFIRST;
url := GETURL(DEFAULTCLIENTTYPE,COMPANYNAME,OBJECTTYPE::Page,PAGE::"Customer Card",Customer);
MESSAGE(url);
  • Close, save and compile the codeunit.
  • From the Development Environment run the codeunit. A message should appear on screen with the url that was generated. In the example below, my default client was set to be the Web Client.
http://localhost:8080/DynamicsNAV100/WebClient?company=CRONUS%20USA&page=21&bookmark=27%3bEgAAAAJ7CDAAMQAxADIAMQAyADEAMg%3d%3d

Hopefully you get a sense now of how you can condition your code based on the different Dynamics NAV client types.

That’s all for today!

A promise of sorts

Well, I’ve not exactly been very active with this site. A smattering of posts over the years, but nothing too consistent.

I am putting up this post to hopefully energize myself into committing to putting up more posts on a more frequent basis.

You see, while I am a developer at heart, I only recently got back into development full time, and it is amazing!! So amazing, that I have been going full steam ahead not looking up from it.

What am I doing? Well…….I’ve climbed aboard the Dynamics 365 for Financials train, and I’ve been busily building an app (or two!) that at this time, has been validated by Microsoft and is just waiting to be deployed to AppSource.

So, back to the point. I am going to try and do better here. I have learned a lot of information that I have found is not as easy to come by as it probably should be, especially being an early adopter that’s moving full steam ahead with NAV extensions. My goal is to be able to put up little tidbits (and bytes! haha, see what I did there?) of things I come across so that perhaps it’s not as hard for the next developer to get this information.

We’ll see how it goes….

Project ‘Madeira’ comes to Canada

Announced yesterday at Microsoft’s Worldwide Partner Conference, the Project ‘Madeira’ preview, an integral part of the upcoming Microsoft Dynamics 365 platform, has been launched to Canadian users! By signing up with a Canadian Office 365 account, you’ll be able to access the platform with a Canadian-centric database.

Click here and sign up today!

AboutDynamics365.png

Also announced, is that the product will be launching to the US and Canada in the Fall of 2016.

MadeiraRoadmap

For more info on what Project ‘Madeira’ is all about, check out my previous post on the topic.

 

Timestamp fields in Dynamics NAV 2016

Have you ever needed to keep track of when records changed, or have you ever had to do an integration where you want to make sure you keep records in synch across multiple systems?

For master records, this was not a huge chore, as you typically were able to use the Last Date Modified field (if there is one of course), but of course you better hope that all updates to the record call the onModify() trigger. For transactional records though, this became more of a chore, as you would need to either keep track of the last entry you synchronized, or figure out some other way of keeping track what you’ve synched and what you haven’t.

I remember a particular integration that I had to do in which involved synchronizing the Item Ledger Entry table. Sure, I could keep track of the last entry no. so I could easily find all new records since the last synch session, however what became difficult was finding all of the older ledger entries that were updated as inventory transactions were applied to them. Remember that the Item Ledger Entry table is unique in that it gets updated even long after they get created.

Enter the Timestamp field. New to Dynamics NAV 2016, it will simply these types of integration and synchronization scenarios. As far as I can remember, all versions of Dynamics NAV running on SQL Server have had an internal system field name that holds the record timestamp. You could however, only access this field by querying the SQL table directly. Anything done via NAV would never even see the field.

Now with Dynamics NAV 2016, you have the ability for all records to determine which records have not only been inserted, but also modified. You still need to track your date/time reference (e.g. the last time the synch was run), and you are still left to determine what to do if records are deleted, but overall, this is a great new feature to the product!

Here’s how to use them…

  1. In any given table, create yourself a custom field, and assign it a Data Type of BigInteger. The name of the field can be anything you want.

  2. View the Properties of your new field, and set the SQL Timestamp property to Yes. It’s probably a good idea to make it a non-editable field as well, just for logic sake.

  3. Close, save, and compile your table.
  4. Voila, when you run the table, you now how your timestamp!

Umm, ok Mr. Blogger, I get all of this, but that field definitely does not contain either a date or a time!! What’s up with that??

Yes…this is true; the field does not actually hold date or time information. What it does hold though is a “version numbering” that is assigned to each row in a table, across all tables in the database, so every row in the database will have a unique timestamp value. This means that no matter what table you are dealing with, you can use a single reference timestamp and obtain all records that have been added or changed. AWESOME!
(as I said above though, finding deleted records is still a chore that requires coding)

One more note on Timestamp fields. You cannot add them to a table key, however you can still perform a SETCURRENTKEY using the timestamp, since NAV now allows us to sort on any field regardless of it being in a key or not.

So now you know, hopefully you can use this new feature to your advantage.

Happy coding….

MG

Hello Project “Madeira”

Today, Microsoft unveiled a major effort they’ve been working on, codenamed Project “Madeira”.

ProjectMadeira

What is it? Simply put…..this is a preview of Microsoft’s offering of a fully cloud-based ERP system. Geared towards small and mid-sized companies, Project “Madeira” is a simple to sign-up, no footprint browser-based software package that provides all of the tools necessary to manage a business……and it’s available on your mobile device too.

Even simpler put……….it’s FREAKIN’ AWESOME!

Oh, and it is DEEPLY integrated into Office365 as well, so managing emails, or exporting data to Excel is a snap on any device!

If that’s not enough, it’s incredibly easy to connect Power BI to your Project “Madeira” system for incredible insights into your business data.

Currently, the preview is only available in the US, but I imagine it’s only a matter of time for that to change. If you just can’t wait, sign up for a free 1 month trial US O365 account to get access now.

A goal of Project “Madeira” is to make it easy for companies to move to this new platform, and this is evident in the sign up process. You can choose to create an empty company, and then simply upload your existing data into it. For those that are using QuickBooks, there is an extension that once enabled, lets you upload data directly from an Intuit Interchange Format (IFF) file. If that doesn’t float your boat, or if you need to ‘clean’ your data first, you can also use Excel files.

Extensions……what are those you ask? Think of these as pieces of functionality that you can turn on and off. This not only means that you can run your ERP in the cloud, but you can tailor your system with the functionality that you need!

Currently, there are 3 extensions available in the preview, but you can rest assured that many more are on the way:

Ok, enough reading about it, go try out the preview!!.