AL Extensions: Custom Build Process Using Visual Studio Code Tasks

I recently discovered the Tasks menu in Visual Studio Code and after a bit of wondering why I’ve not seen it after using VS Code for many months, I then took a quick look into what it was all about.

Turns out VS Code has yet another amazing feature called Tasks, which let’s you automate things such as builds, packaging, deployment, and probably whatever else you can think of. You can read all about tasks in detail here.

This got me thinking, I wonder if I can use this to make my own build process for AL extensions? Turns out this is quite easy…and here’s how you can do it.

Open up your AL extension folder and select Tasks > Configure Tasks.

TasksConfigureTasks

In the command palette select Create tasks.json from template.

CommandBoxConfigureTasks

In the command palette select Others.

CommandBoxSelectOthers

You’ll now see a tasks.json file create in the .vscode folder of your AL project.

tasksJsonFile

In the tasks.json file you’ll see some default settings like this:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "echo",
            "type": "shell",
            "command": "echo Hello"
        }
    ]
}

We need to change the task command so that we build our AL extension. When you install the AL Language extension, behind the scenes is installed a command line compiler (alc.exe). The alc compiler accepts 3 parameters:

  1. project: The path to the AL project folder
  2. packagecachepath: The path to the folder containing the reference packages
  3. out: The path to output the packaged extension app file to. This parameter is optional. If it’s not specified then the compiler will output the app file in the project folder with the default name of <Publisher>_<Name>_<Version>.app

For example, in order to build our AL extension with the default output and name, we’d need a command such as this:

C:\Users\<username>\.vscode\extensions\Microsoft.al-0.10.13928\bin\alc.exe /project:C:\ALProject1 /packagecachepath:C:\ALProject1\.alpackages

One more quick thing before we continue. Within VS Code tasks, you have access to some predefined variables. You can read about what they are here. For our task, we’re interested in the ${workspaceFolder} variable, which will give us the path to the workspace folder of the project.

Back to the VS Code task. We need to update the tasks.json file now. We’ll change the taskName property to a more meaningful name, and we’ll update the command property to execute our alc compiler. Make sure to note the double slashes and that you replace the <username> and AL Language extension version number with the correct one as per your environment.

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "Offline Build",
            "type": "shell",
            "command": "C:\\Users\\<username>\\.vscode\\extensions\\Microsoft.al-0.10.13928\\bin\\alc.exe /project:${workspaceFolder} /packagecachepath:${workspaceFolder}\\.alpackages"
        }
    ]
}

Now that we’ve updated the task file, you need to set this task as the default build command. To do that you select Tasks > Configure Default Build Task from the menu. Doing this will not change the existing F5 or Ctrl+F5 commands that Microsoft delivers with the AL Language extension.

TasksConfigureDefaultBuildTask.png

In the command palette select the name of the task you created above. In my case, I’ve named the task Offline Build.

CommandBoxSelectTaskName

The following lines were just added to your tasks.json file:

"group": {
    "kind": "build",
    "isDefault": true
}

You can close and save the tasks.json file now if you still have it open. You’re ready to use your new build task in the following ways:

  1. Tasks > Run Task
    • With this method you can select to run any task that you’ve created.
  2. Tasks > Run Build Task
    • This will work only if you’ve made your task the default build task.
  3. Ctrl+Shift+B
    • This will work only if you’ve made your task the default build task.

No matter what method you choose to execute the task, you can monitor it for errors in the VS Code terminal window.

TerminalWindowOutput

That’s it! Now you’ve got a way to build your extension without having to deploy it at the same time.

Pretty sure I’ve only scratched the surface on what VS Code tasks can do, so I’m excited to see how else I can make use of them in my AL development.

Until next time…..happy coding!

 

 

Advertisements

AL Language Extension in Marketplace

For those of you that have been trying out the Dynamics NAV Development Preview, you can now grab the AL language extension from the Visual Studio Code marketplace.

This will let you set up your local machine for coding and deploying extensions on the v2 platform. This version of the AL Language extension is not for coding against an on-prem NAV system. It requires a Dynamics 365 for Financials Sandbox tenant.

To get the AL Language extension, just do the following:

In Visual Studio Code, click the Extension icon at the left and in the search box at the top, type in AL

Capture.PNG

In the search results, select the AL Language extension, and click Install.

InstallAL

After it is installed, click the Reload button to reinitialize Visual Studio Code with your new extension.

ReloadAL

That’s it! You can now connect your AL Language extension to your sandbox environment and code away!

As always, happy coding!

New Development Tools – April Update

As all Dynamics NAV developers probably know by now, Microsoft is working on the next generation of development tools for working with Dynamics NAV and Dynamics 365.

They’ve just released the April update, and included in this update is the tool to convert your v1 extensions to the new v2 format. Exciting!!!

Check out what else is new in the update here.

Find Out if an Extension is Installed, part 2

“Hi, this is Library, is Extension 1 home? What about Extension 2, are they home too?”

In my previous post on this topic, I explained how you can use the NAV App Installed App system table to see if a specific extension is installed. I later found out though that the ability to access that table may not always be available in the Dynamics 365 for Financials platform, so back to square one. I want a stable long-lasting solution.

Alas…events!

First…some background on why I need this functionality. I’m developing 2 extensions that share a common library, but I want to develop these extensions so that they are independent, meaning that a customer is able to install only one of the extensions if they choose to, and not be forced to install both. I also need certain features in each extension to act differently depending on if the other extension is installed or not. I know….never simple. 🙂

For those that are not aware, when you submit an extension to AppSource, you are able to submit along with it a library extension. Multiple extensions can be dependent on the same library, which makes it easy to deliver foundation type functions that are shared amongst your extensions. The library extension will not be seen in AppSource, but it will be automatically installed when any of the dependent extensions are installed.

What this also means is that when I am developing in the context of one of my “functional” extensions, I am able to directly reference objects that are contained in my library because the library is guaranteed to exist when the functional extension is installed. What I cannot do though is the opposite, because although the library extension knows that at least one functional extension was installed, it does not know directly which one it was. Make sense!? Clear as mud I know. 🙂

In the example below, let’s assume that I have a “Library” extension, and two functional extensions, brilliantly named “Extension 1” and “Extension 2”.

First, I need to create a codeunit in my library extension that will act as the “extension handler” so to speak. In other words it will house the functions required to determine what extensions are installed. In my library codeunit, I’ll add the following functions:

CheckIsExtensionInstalled(ExtensionAppID : GUID) : Boolean
IsInstalled := FALSE;
IsExtensionInstalled(ExtensionAppID,IsInstalled);
EXIT(IsInstalled);

GetExtension1AppID() : GUID
EXIT('743ba26c-1f75-4a2b-9973-a0b77d2c77d3');

GetExtension2AppID() : GUID
EXIT('a618dfa7-3cec-463c-83f7-7d8f6f6d699b');

LOCAL [IntegrationEvent] IsExtensionInstalled(ExtensionAppID : GUID;VAR IsInstalled : Boolean)

The above functions allow me to call into the codeunit to determine if either of my functional extensions are installed. The GUIDs that I used are samples above, but you should use the same GUID that is used in the corresponding extension manifest file.

The piece that makes this all possible is the published event IsExtensionInstalled. What I can do now is from within each functional extension, I can subscribe to that event so that each extension can basically give “answer” the library when it asks if it’s installed.

To do that, I create 2 more codeunits, one in each functional extension. These codeunits will contain a subscriber to the event that we published in the library codeunit. This way, if the extension is installed, its subscriber will respond to the event and let the library know that it is installed. If the extension is not installed then there won’t be anyone home to answer that call.

Extension 1

LOCAL [EventSubscriber] OnCheckIsExtensionInstalled(ExtensionAppID : GUID;VAR IsInstalled : Boolean)
IF ExtensionAppID = ExtensionHandler.GetExtension1AppID THEN
  IsInstalled := TRUE;

Extension 2

LOCAL [EventSubscriber] OnCheckIsExtensionInstalled(ExtensionAppID : GUID;VAR IsInstalled : Boolean)
IF ExtensionAppID = ExtensionHandler.GetExtension2AppID THEN
  IsInstalled := TRUE;

So how do we use all of this? Easy, of course. The example below shows code that you could use from either of the functional extensions, so that your extensions can act differently depending on what other extensions are installed.

IF LibraryCodeunit.CheckIsExtensionInstalled(LibraryCodeunit.GetExtension1AppID) THEN
  MESSAGE('Extension 1 is installed.');

IF LibraryCodeunit.CheckIsExtensionInstalled(LibraryCodeunit.GetExtension2AppID) THEN
  MESSAGE('Extension 2 is installed.');

There, easy right? If you want to try it out yourself, you can grab the above example on GitHub here.

Now, while you can do this if you own all of the source code for each extension, you cannot use this solution to determine if “any old random extension” is installed, as you need to add the subscriber function to the functional extension code. But, if you are developing out multiple extensions and if you need to know which of them are installed, then this solution will work wonderfully!

Happy coding!

Published!

Well, it finally happened…..

The Dynamics 365 for Financials extension (or app…..your choice) that I’ve been working on has finally made it to AppSource! You can check out our listing here.

untitled

BuildFood – Recipes is the first extension from IndustryBuilt Software Corp., who also happen to make JustFood. The extension focuses on the needs of the small bakeries out there, and as the marketing gurus say, it can

“manage recipes, create ingredient declarations, track allergens and calculate nutrients.”

With the extension being validated back in November, it has been a somewhat lengthy wait before seeing it published, but it’s awesome to see it available now! When we first formed the “extension team” as it was first referred, we weren’t sure what to expect from this “new way” of building solutions, and it became evident early on that we needed to tackle everything (marketing, product design, development) with fresh eyes and a new point of view. I think everyone involved has done a fantastic job of that if I do say so!

So……we’re published. Cool….but we are not stopping yet! We’re not too far from submitting the next version of BuildFood – Recipes to AppSource so stay tuned for that! Some great new features coming in the next version! We’re also working on our second extension, but I’m not giving away any details on that until marketing has their chance to let loose with it. 🙂

Oh, if you want to know more about BuildFood, click here!

Happy coding…

 

Back from Copenhagen…

I’m writing this on the plane heading back to Toronto after spending a few days at the Microsoft Development Center in Copenhagen (great building!!). I was participating in a set of meetings around how to wow the Dynamics 365 for Financials customer.

It’s all about the customer experience, or the journey if you will. From the time they select and install an extension, the customer needs to have an experience that makes them want to continue, and makes them want to register and purchase your extension. Let’s face it, first impressions are huge, especially in a SaaS world where choice is king. If a customer needs to jump through hoops to get your extension setup before they can even try it out, chances are they’re going to move on.

While I can’t get into the details as they are yet to be made public, what I can say is that it was great for IndustryBuilt Software Corp. to be included in the select group of partners that were chosen to participate alongside some key Microsoft resources, in order to help define the standards that all partners can (and I hope will!) adopt in order to make their extensions great. A ton of ideas were discussed and everyone came away from the meetings with new information on how to not only improve their own extensions, but ways in which we can create tools and samples that other partners can use. Can’t wait to see all of the final products!

As an added bonus, I spent a bit of time playing with extensions v2, which I’ve been wanting to do for a while now. I even begin converting my existing v1 extension into a v2 extension, and conversion process is slick. There’s always clean up to be done after any conversion tool, but it gets you close! The tool is not available yet so I’m not spilling any beans on it now, but I’ll be working with Microsoft to resolve some of the issues that I did encounter, so perhaps I can share more information later.

That’s it for now, and as I said, more information will come on this when it has been made public, but for now, rest assured there is a strong dedication and commitment from Microsoft on ensuring that whether the customer is new to ERP or they’re a seasoned veteran, their software experience will be fantastic!

NAV Development Preview – February Update is Here!

If you are a Dynamics NAV developer you should hopefully have heard by now of the upcoming changes to the development environment for building extensions.

If you’ve not heard about this, read about it here. In short…Visual Studio Code! Oh….and if that isn’t enough, we’re getting an in-client visual designer as well!

Unfortunately I’ve not had as much time to play with it as I would have liked. I am hoping to change that in the next few weeks. From what I’ve seen though, I cannot wait to start using it on a daily basis!

The team at Microsoft has been doing a great job delivering updates since the initial preview release in December. Check out the latest release notes here and try it out if you can!