A week ago I wrote a post for answering a question regarding how to print external documents from Microsoft Dynamics NAV. This code is C/AL based and it uses DotNet classes that interacts with the local operating system.
How can this code be translated as Extension for Dynamics 365 Business Central?
For the SaaS version of Dynamics 365 Business Central, this is actually not possible. We can’t use DotNet objects in the cloud. But what about the future on-premise version?
This is currently in preview (so you don’t find this feature in your standard sandbox environment) but starting from build 13.0.22895.0 you can call .NET types from AL code if you’re targeting an on-premise deployment.
To use a .NET type in AL, you need to start by declaring a dotnet package:
dotnet { }
then you add a declaration of the assembly that you want to reference (one or more than one):
dotnet { assembly(YOURASSEMBLY) { } }
and finally you have to add a reference to a .NET type from the referenced assembly (by using the .NET fully-qualified name and giving it an alias that you will use for referencing the .NET type from AL code):
dotnet { assembly(YOURASSEMBLY) { type(YOURDOTNETTYPE; ALIAS) {} } }
So, how can we transform our previously developed C/AL code for external document printing to be used in AL for the next on-premise Dynamics 365 Business Central version?
The first thing to do is starting a new AL project with Visual Studio Code, open the app.json file and insert the following line:
This means that your extension is targeted for the on-premise deployment.
Then (extremely important!), you need to instruct the compiler where it has to search for assemblies. By default, the compiler only knows the location of the mscorlib assembly. To add new assembly paths for the compiler, you need to open Visual Studio Code user settings and add the following lines:
The “al.assemblyProbingPaths” setting instructs the compiler where to search. Restart Visual Studio Code after adding this setting.
After that, you can start coding. Exactly like in the C/AL sample, I have a codeunit that does all the tricks. In my AL project, I’ve created a codeunit called DotNetWrapper that:
- Declares the DotNet assemblies that I need to use
- Declares the functions that uses the DotNet variables and performs the actions
The AL codeunit is as follows. First, we declare our .NET assemblies:
and then in our functions we can use the .NET types by declaring DotNet variables:
Having DotNet variable support for the on-premise is a must and now we have a great way to handle these scenarios. What about the SaaS? Nothing change for the moment 🙂
P.S. a small note about a noisy effect I’ve observed in Visual Studio Code when declaring the dotnet package: VS Code could give you an error indicating that the .NET assembly cannot be located. First, restart VS Code. If the error persists, just force a compilation and it will magically disappear.
Hey guy, I followed your instructions, but still I am not able to create objects of the DotNet data type. Visual Studio Code permanently shows me the message: “[AL] This feature is under. It can be enabled by using the dotnet feature flag.” Do you know how to solve this?
LikeLike
This feature is actually available only in the insider preview (starting from build 13.0.22895.0) and by placing target = internal in app.json.
LikeLike
And how can I find out, which version I have? Or how can I get the insider preview?
LikeLike
I think you have the actual version of BC, so 12.X. The insider preview is available if you are enrolled in the Collaborate program: https://docs.microsoft.com/en-us/collaborate/registration
If you can wait few months, this will be released for all.
LikeLike
At the moment I am working only locally, that is why I have no BC yet. O I need this version, even if I only want to create locally on my computer objects of data type DotNet without using BC?
LikeLike
You need to have the AL Language Extension that’s actually available only in this insider preview.
LikeLike
I have the AL Language Extension, it is the version 0.15.18…
LikeLike
You need 0.17.X (only available as said before in insider preview).
LikeLike
Now I understood^^
Do you also know, whether we can generate objects of the data type automation with the new version?
LikeLike
If you run this code (F6) against the 13.0.24623 you get a nice error
Something went wrong.
Er heeft zich een fout voorgedaan
Date and time: Mon, 01 Oct 2018 13:38:28 GMT
At that point you’re just starting up the webclient, so the issue is releated due to
dotnet
{
assembly(System)
{
type(System.Diagnostics.Process; Process) { }
type(System.Diagnostics.ProcessStartInfo; ProcessStartInfo) { }
type(System.Diagnostics.ProcessWindowStyle; ProcessWindowsStyle) { }
}
}
or
If you debug this code (F5) against the 13.024623 you get the rolecenter.
Running the code doesn’t do anything, no error, no printing.
Even tried with the runonclient
local procedure PrintDocument(Path: text)
var
ProcessInst: dotnet Process runonclient;
ProcessStartInfoInst: dotnet ProcessStartInfo runonclient;
ProcessWindowStyleInst: dotnet ProcessWindowsStyle runonclient;
Same behaviour
LikeLike
Thanks for the information. I followed your instruction and it worked great but found out a few days later that for some reason the dotnet definition included (identical to yours) breaks user personalization and I cannot figure out why. Any Ideas?
LikeLike
Wha do you mean with “breaks user personalization”?? Sounds strange…
LikeLike
It is very strange and I cannot figure out how the two are related. Basically if I have the dotnet lines enabled and run my extension and click on personalize anywhere in the system it brings up a message box “Personalization could not be enabled due to technical issues. Try again later, or contact your system administrator.”
Commenting out the lines fixes the issue. We are using a third party extension (PrintVis) as a base so I was wondering if it was conflicting somehow with something they have done but so far it doesn’t make much sense.
We also already use System.Data from botnet elsewhere in our project with no issues.
LikeLike
We just resolved it. We found when we had a dotnet definition in two files it would cause this issue so merging the two definitions solved it.
LikeLike
Hi, It’s possible with Business central 18.1 it’ doesn’t work ? No error but nothing appends …
LikeLike
This code was an old code for BC 13. It uses .NET variables to call the Print verb of the server OS. Never tested with next releases. The file path must be reachable from the server (service tier).
LikeLike
is it possible to specify the name of the printer to use with this method?
LikeLike
I think that you can pass the printer name as arguments: ProcessStartInfo.Arguments = PrinterName;
LikeLike
Use
processStartInfo.Verb := ‘PrintTo’;
with ‘Print’ it takes the Default Printer.
LikeLike