The new code editor in Dynamics NAV

I have really tried to like, even love this editor. But every time I’m using it, it keeps fighting the C/AL syntax and the way C/AL is usually typed. This is actually a step back in productivity for me.

The editor is missing several context aware features that is essential for programming in C/AL – and it even changes correctly typed code into wrong code.

1. Inside a field name with multiple name parts.
Try to type:
GLEntry.SETFILTER(“Dimension Set ID”);
This is what you’ll get if you just type:
GLEntry.SETFILTER(“Dimension SETDEFAULTTABLECONNECTION ID”);

Try to type:
rec.SETRANGE(“Account No.”);
This is what you’ll get if you just type:
rec.SETRANGE(“Account NORMALDATE”);
Cause the dot in No. gets completed to NORMALDATE

2. Field Name parameters to functions like Rec.SETRANGE()

3. Parameters to functions that takes multiple field name like SETCURRENTKEY, CALCSUMS and CALCFIELDS.

4. You can place the cursor on the line for a function definition, but you cannot do anything more. Accept a Enter Key press to insert a new line at the top of a code section would be very nice.

5. You can DOT yourself via intellisense into the options on a option field, and  the source will written with a dot separator, but not the required :: separation. If you type colon the system does this correctly.

6. If a field in Rec has multiple name parts, and you start typing with the double quote ” the intellisense will not show the fields names.

7. Visual Studio is clever enough to figure out that if you type a name or symbol that will un-indent the line. NAV does not do that, so I end up spending more time on fixing indentation than I would if the editor didn’t try to “help” me.

8. When indented, and I want a blank line and pressing enter twice, that will often result in a cursor placement in column 1. (Leftmost)

The TODO list to salvage this editor.

Learn the language – The parser of C/AL needs to understand Pascal based syntax, this is the basis for any “intellisense” functionality to be intelligent.

If I just type code, letter by letter, the intellisense should NEVER change my correctly typed code into wrong code, this is the first rule for any “smart editor”.

Be aware of the open ” (double quote) state – this would solve most of my issues. Either figure out what field list to show as “intellisense” or simply don’t show anything.

There is an option to use the old editor with FINSQL.EXE

[useoldeditor=<yes|no>]

But as I started out, I really want to use the new one, so here’s hoping for the next cumulative updates :)

Export NAV license from SQL Server

Microsoft Dynamics NAV does not give you an easy an option to export the NAV license from a SQL Server.

exportlicense1

You can upload to the server, or temporary change the license that is used in the development client, but you cannot download it again. Usually, that is not a big deal, you got your license file anyway, but in some cases, its practical to be able to export the license.

With NAV, the license can be placed in two different places, in the master database or in separate databases.

exportlicense3

If you check the “Save license in database”, the licens goes into the database, otherwise its stored on the server.

Introducing a simple tool to perform the export

exportlicense2

This tools will export the license file from the SQL server and database specified. If you leave the database field empty, the tools will export the license stored in the master database.

Download from here: ExportLicense

(13/2/2016: Updated to better handle SQL servers with different collations)

Or grab the source from github:
https://github.com/hougaard/ExportLicense

Change your way – Functional Programming In Dynamics NAV

I’m always ranting about “do not use global variables” in Dynamics NAV, this article is an attempt to give some backgrounds on the ranting.

In Microsoft Dynamics NAV we program in a language called C/AL, this language is related to Pascal, a language created by Nicklaus Wirth in the late 60’ties. Pascal belongs in a language family with Modula-2, Oberon, Delphi and many others.

Fun fact, one of the first Pascal compilers was written in Pascal and translated by hand into machine code by Wirth and his students.

And a fun relation between Dynamics and the history of Pascal. The man behind some of the most success Pascal compilers, PolyPascal, Turbo Pascal and Delphi is Anders Hejlsberg and his brother is Thomas Hejlsberg, one of the architects behind Dynamics NAV.

In the late 80’ties when PC-Plus (later Navision Software, later Microsoft) designed the first version of AL, Pascal was the most popular programming language in Denmark and a natural language choice for a new development system.

The first version of AL (character based version 3.00) worked with objects just as we know it today, but it was very limited compared to what we have today. The name later changed to C/AL with the release of the first Windows version, called Financials.

One of the main limits in AL was the lack of local variables. This of cause  lead to a heavy use of global variables (just called variables since there where no local><global definition). This continued into Financials even though Financials did have locals. The reason was, that parts of Financials was actually coded in the old character based version and the converted to Financials with the auto-converter.

So the reason that we are still fighting with less than optimal designed codeunit 80 and 90, is that they where programmed in a environment without local variables, limited call stack levels and other limitations.

So why does local variables matter?

First we need to look to another branch of programming. A branch called functional programming. The origin is math and a language called Lisp. Lisp is older than Pascal, and actually one of the very first programming languages. Lisp is often ridiculed due to a massive usage of parentheses and the beauty is overlooked.

I had my first encounter with Lisp at Copenhagen University, where they decided that we should learn a language that no-one had ever used, that turned out to be Lisp, followed up with ML. I learned a lot :)

In (purest form of) Lisp you don’t have global variables, and the only local variables are parameters to functions. So everything needs to be functions with parameters and return values.

This can be much harder to program, but is much easier to test.

There are plenty of other languages that follows the tradition started by Lisp – My current favorite is F# but I do have fond memories of ML (If I could find a compiler that worked back in the 90’ties).

The style of programming in these languages is called Functional Programming.

So what are some of the features in Functional Programming?

First-class and higher-order functions

A function is a value, just like an Int or a String. You can pass a function as parameter to another function. This is not really possible in NAV, only by some clever .NET tricks for creating delegates.
A classic use case for this, could be a sorting function that takes a comparison function as a parameter.

Pure functions

Think of a function as a mathematical function, it takes parameters and returns a value, nothing more nothing less. No side effects. When we throw a database in mix, this get more complicated.

Recursion

Recursion is not a functional programming exclusive feature, recursion was actually invented before Lisp, in the language ALGOL, by another Dane, the late Peter Naur. But recursion does not work well in a global variable dominated system.  Recursion can place a bigger strain on memory usage unless system support tailcall optimization a method to reduce the amount of call stack memory needed for keeping each recursion level in memory.

No side-effects

A side-effect is when a piece of code modifies anything outside its scope. A global variable is outside the scope of a function. The database is also very outside.

In a pure functional environment, there are no side effects.

Classic code mistakes in Dynamics NAV

So if we start looking at NAV code, with the knowledge of functional programming, what “mistakes” could we try to avoid:

Global variables should be avoided. Global variables, if used, should be immutable, a fancy computer science word for “readonly after create”, once written, never overwritten.

Hang over filters” – This is actually globals-on-globals. When people reuse the same Record variable and the properties on the Record stays on the Record. So everytime you use the .RESET function on a record variable, you’re properly doing something wrong. If Microsoft removed .RESET method, your code would actually improve, cause you would be forced to think about scope, and in a lot of places place inner code in loops in separate functions.

Real recursion only works if the globals are reduced to immutable usage.

Big functions – The only reason that functions can get so big are globals (again!) So if you reduce the amounts of globals, your functions will shrink in size.

What about testing?

A function that only takes parameters, and returns a value is very easy to test. You can just call the function and verify the return value with a test codeunit. But if you need to setup global variables and environment, then it suddenly becomes difficult to test the function, and usually you start your testing at a higher level. And if the higher level also has the same issues, testing becomes hard.

Conclusion – TL’DR

These ideas has been a integrated part of how I program for many years. Not that I’m “holy” or even close to that. But I do believe in “borrowing” good ideas from all corners of the computer science world. And functional programming has, for me, a very positive influence on how programs get structured and how easy they are to test and maintain.

There are lots of other aspects in functional programming that I didn’t cover in this already too long blog post, so reach me on Twitter if you want to talk function programming in Dynamics NAV.

(*) Thanks to www.xkcd.org for the comics to live up this boring tale.

Better browser support for Control Add-ins in Dynamics NAV

Microsoft Dynamics NAV uses a .NET web browser control to display Javascript control add-ins. This is great, but .NET by default chooses to use a rather ancient version of Internet Explorer (IE7?) to handle this. This creates, in some cases, an less than optimum  user experience.

The problem becomes even bigger, when an installation has both RTC and web clients. In that case user could get different functionality from control add-ins due to different versions of IE used.

To fix it, a registry key must be added to all client machines running the role tailored client.

This piece of code will add the required registry key to the users machines and allow NAV to use the newest version of IE. All varibles MUST be “RunOnClient”, otherwise you will just be setting registry keys on the service tier server.

This code set the required IE version to 0 –  If you want a specific IE version, check this

IF Environment.Is64BitOperatingSystem THEN
  RK := RK.OpenBaseKey(RegistryHive.CurrentUser,RegistryView.Registry64)
ELSE
  RK := RK.OpenBaseKey(RegistryHive.CurrentUser,RegistryView.Registry32);

RK2 := RK.OpenSubKey('SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION', RegistryKeyPermissionCheck.ReadWriteSubTree);
IF ISNULL(RK2) THEN BEGIN
  RK2 := RK.CreateSubKey('SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl', RegistryKeyPermissionCheck.ReadWriteSubTree);
  RK2 := RK.CreateSubKey('SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION', RegistryKeyPermissionCheck.ReadWriteSubTree);
END;
RK2.SetValue(Process.GetCurrentProcess().ProcessName + '.exe', 0, RegistryValueKind.DWord);
RK2.Close();
RK.Close();

Here is the code as a  NAV2016 codeunit – Download it if you like better webbrowser with addins

How should I deploy a new Microsoft Dynamics NAV 2016 installation?

I’ve just got that question from a good friend, and though that I would write up my answer.

The short answer is, use Azure SQL !

If you haven’t heard about Azure SQL, let me explain it. Azure SQL is “SQL as a service”, you’ll get databases deployed in any Microsoft Azure data center that works, looks and feels just like databases deployed on a good old fashion SQL Server(*). But you get the database without having to pay for or install:

  • Hardware for Server, storage, backup network..
  • Server maintenance
  • SQL Server license
  • 3rd party backup software license
  • Redundancy setup

Paying for Azure SQL is also very simple, you select a performance level, measured in Database Transaction Unit (DTU) and you get the performance. If you need to double your performance for a limited time, you can just select (and pay for) a higher DTU level, and when the need is over, go back to the old level.

A Database Transaction Unit is a artificial measurement composed of CPU, Memory, input and output. If you want to double the performance of your SQL database, you simply upgrade to the double DTU level. Visit this page for more information, and if you want to get the DTU level from your own server, go here.

I start a NAV database out on level S1 (20 DTU), around $40 pr. month. Can you run SQL Server on a physical or virtual server with redundancy and real time backup for $40 pr. month? SQL Server is a very expensive piece of software, and the correct hardware to run it is just as expensive.
And if you want geo replication of your database to a different data center, its just a few click away, and the cost is just another database.

When it comes to backups, Azure SQL has a “down-to-the-minute” 14 days automated backup available – So you can restore a copy of your database from almost anytime going 14 days back. It is possible to transfer backups to and from Azure using a file format called Bakpac (In SQL Management Studio it is know as a import or export a “Data-tier application” – don’t let that fool you, its just a fancy name for backup and restore).

When you have your SQL database in Azure, you have to place the NAV service tier in Azure also – and in the same data center as the database. The service tier must be deployed on a virtual machine.  When dealing with modern NAV, network performance between SQL and the service tier has to be high speed. The network performance between the service tier and the client  can be lower without causing problems for users.

Installing the service tier in Azure will also ease the access to the system from the new tablet, phones and web clients.

Each vm in azure gets a myname.cloudapp.net DNS name. To run the other client with NAV you will need a HTTPS connection with a valid certificate. The way I usually setup this up, is to create a CNAME dns entry on the customers domains and have that point to the cloudapp.net name. Then you can use IIS on the vm to create a certificate request and install a valid certificate.

Security is also quite simple, you control what IP addresses that can have access to the Azure SQL server/database, in this case, its usually only “Azure Services” (other machines in Azure) plus your local gateway (for admin tasks).
You can control access to the service tier with either a azure virtual network plus VPN or classic firewall setup. If this is a standalone machine in Azure, remember to create it as “Classic vm” to have the simplified endpoints and security model.

“But a server in my basement is much more secure than in the cloud!”
No, it’s not. It may seem that way, but both physical and virtual security is much better in a cloud environment like Azure than a self maintained old-fashion server room. You have state-of-the-art security setup, equipment and 24/7 staff monitoring the entire thing and everything is sitting inside military grade buildings with redundant power and connectivity.

Throw questions at me on Twitter @eHougaard if you feel I’ve left something out.

Small Update

This is in reality the exact same building block Microsoft uses for its new managed Dynamics NAV service.

(*) There are a couple of small differences, but they really don’t matter when it comes to NAV2016:
  • Authentication cannot be Windows since the Azure SQL service does not run in your AD (This might chance)
  • A database has no concept of “files” and filegroups
  • Tables much always have a primary key
But NAV 2016 works perfectly on Azure. NAV2015 and older does not.

Microsoft and communication ?

When downloading a Dynamics NAV cumulative update from Microsoft, you will get this message before being able to download anything:

WARNING   This hotfix has not undergone full testing. Therefore, it is intended only for systems or computers that are experiencing the exact problem that is described in the one or more Microsoft Knowledge Base articles that are listed in "KB Article Numbers" field in the table at the end of this e-mail message. If you are not sure whether any special compatibility or installation issues are associated with this hotfix, we encourage you to wait for the next service pack release. The service pack will include a fully tested version of this fix. We understand that it can be difficult to determine whether any compatibility or installation issues are associated with a hotfix. If you want confirmation that this hotfix addresses your specific problem, or if you want to confirm whether any special compatibility or installation issues are associated with this hotfix, support professionals in Customer Support Services can help you with that.

Really, so CU’s are not intended for general use and Microsoft does not think customers should update on a regular basis?

Wait for a service pack? Haven’t seen any of those since NAV 2009.

My guess is that this is just a “standard” warning you get whenever requesting a “hotfix” from Microsoft, if that is the case, maybe the NAV Team need to consider a different distribution model for NAV updates.

NAVY: A package manager for Dynamics NAV

After a discussion at the MVP Summit between some of the NAV MVPs a idea of an alternative to Microsoft’s new extensions appeared. And after some hours of coding, and about ~400 lines of code, here is “NAVY” – Microsoft extensions are called NAVX – Y is coming after X  therefor NAVY (Thanks Waldo).

This package manager is created for OnPremise installations, for installing verticals and horizontals into a standard NAV. Currently multi-tenant setup is not on my mind.

A NAVY package consist of metadata, new objects as FOB or TXT and DELTA files for changed standard objects.

NAVY can perform 5 operations:

  • BUILD a NAVY package with FOB/TXT objects and DELTA files
  • INSTALL a NAVY package into a database
  • UNINSTALL a NAVY package from a database
  • SUSPEND a NAVY package in a database
  • RESTORE a NAVY package in a database

The package life cycle

The main idea, is that you BUILD a package and then INSTALL that into a database. When you need to update the standard Dynamics objects you SUSPEND the objects (so the original objects are put back), upgrade NAV and then RESTORE the package back to its intended functionality.  If you want to get rid of the package you will use UNINSTALL so the original objects are reinstalled.

Installation

Download NAVY from here NAVY and extract the files from the zip file. The first thing to do is edit NAVY.exe.config and make sure that the paths points to your Dynamics NAV installation.

I have only tested with Dynamics NAV 2016, but it should work with 2013R2 and newer.

NAVY IS PRE-RELEASE SOFTWARE – DO NOT USE IN PRODUCTION !

Building a package

A package need a FOB file and some DELTA files. If you never have tried to create DELTA files, there are lots of good explanations on the net, here is Microsoft’s:

https://msdn.microsoft.com/en-us/library/dn789715%28v=nav.90%29.aspx

Waldo wrote a lot about it here http://www.waldo.be/2014/07/10/powershell-the-merge-commandlets-for-nav-2013/

A .NAVY file is just a ZIP file, so you can open the package with any ZIP tools.

Installing a package to a database

Installing is easy, make sure your NAVY.exe.config file points to the right executables, after that you simply type:

NAVY install Name=<packagename> DatabaseName=<databasename>

and NAVY will install the package.

After the installation has completed, a .NAVY.Backup file is created with the original objects. This file is required to do uninstalls and suspensions. Keep this file together with the .NAVY file.

Uninstalling a package from a database

Uninstalling a package is just a easy.

NAVY uninstall Name=<packagename> DatabaseName=<databasename>

NOTE: The objects installed from a FOB file is not removed  by the uninstall, only the changes to standard objects.

If fields are added to standard tables, uninstall will delete the field and thereby destroy the data – If that is not what you want, go look at the suspend command

Suspend a package on a database

If you want to upgrade the standard objects, its much easier to do if the original objects are back. This is what the suspend command does:

NAVY suspend Name=<packagename> DatabaseName=<databasename>

This will save values from fields added to standard tables before uninstall the changes and putting the original objects back.

In the .config file, you can specify what object number the table and codeunit used for storing data uses. Default is 50000.

After suspension has completed, you can upgrade NAV and then run the restore command.

Restore a package on a database

The restore command revert the suspension.

NAVY restore Name=<packagename> DatabaseName=<databasename>

The DELTA files are again applied and the saved data is being place back into the new fields.

NAVY is Open Source

Download the source from github, it is just a Visual Studio 2015 C# project with no external requirements. Fell free to change it into something useful. I love pull request :)

Access the source code at: https://github.com/hougaard/NAVY/

Developing for the Dynamics NAV Phone client..

Not every Microsoft Dynamics NAV page works with the new phone client. If you suddenly get a message saying “This task is not possible on your current device. Instead, use a tablet or a desktop computer to complete this task. (ID: xxxxxx)” xxxxxx is the object number of the offending page.

Then you are using a page of type worksheet you will get this error.

QuickMemo+_2015-10-30-12-24-56

How to create a cool LEGO remote controlled car.

In our house we love to play with remote controlled cars. But RC cars in the kid-budget area tend to break after a few hours of use.

Not long ago we shopped a bit a Lego.com and we got some of the “motor” pieces that normally only come with some of the largest Lego Technic sets.

And very quicky, a remote controlled car in Lego Technic was put together, and it actually gave the same play ability as a normal remote controlled car, plus the entire Lego universe. And it seems unbreakable – If something “breaks” – we put it back together again, or perhaps a new car is suddenly a reality.

The center piece is the “88004 Servo motor”, a motor that gives a 180 degrees turn and can be controlled with any of the IR remotes from Lego. We had the IR Receiver (8884) from a Lego train system and we got the 8885 remote controller.

A motor and a battery box is of cause needed, the standard 8293 motor set will do fine, however, if you want more power, the new L-motor or XL-motors are great for speed and power. We use the L and XL motors that reason.

Watch this small video for a demo of the car:

Here are links to the three pieces needed – Total investment if you already have a motor set is $50 – Not bad for unlimited supply of different remote controlled cars.

Servo engine: http://shop.lego.com/en-US/Power-Functions-Servo-Motor-88004

IR Receiver: http://shop.lego.com/en-US/LEGO-Power-Functions-IR-Receiver-8884

Remote Control: http://shop.lego.com/en-US/LEGO-Power-Functions-IR-Remote-Control-8885