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