Table of Contents

Build a Handler

A handler is a Powershell script or an executable that receives two parameters.

The first parameter is a file name that points to the data sent to the handler from Business Central.

The second parameter is a file name that returns data to Business Central.

./handler.ps1 input.bin output.bin

or

./handler.exe input.bin output.bin

Both input and output files are handled as binary files. The content is up to you. Some examples are JSON, XML, CSV, PDF, or images. JSON is handy because the AL language in Business Central has objects to produce and parse JSON files.

Example - Uppercase

Let's build a simple handler to illustrate the process. The handler in this example will return the uppercase value of a text string. We will name the handler UppercaseHandler.

This handler uses two-way communication. It receives a package with instructions from Business Central and returns an answer.

It is designed to run under the direct print service.

Direct printer for handler

Before creating a job on the queue for the handler, we need to define a direct printer. This is not an actual printer, but it will be used to control which service should handle the job and which handler script should be used to process the package.

Direct printers

This printer should place the jobs in the queue so that the service picks them up instead of downloading and processing them on the client computers.

Handler folder

First, we must create a folder for our handler. For security reasons, the handlers are stored in a subfolder of the product's program folder. The subfolder is called handlers. This is the location in a default installation:

C:\Program Files\Reports ForNAV\Handlers

In this folder, we create a folder for our new handler. The folder's name is our handler's name.

C:\Program Files\Reports ForNAV\Handlers\UppercaseHandler

Handler script file

The script is a file in the new folder called handler.ps1.

The handler script reads the input and output file names from the command line arguments.

$inputfile = $args[0]
$outputfile = $args[1]

Then, it reads the package in the input file. We assume the input file is a simple JSON document with a string value called inputtext.

$package = Get-Content -Raw $inputfile | ConvertFrom-Json

The output is also created as a JSON document with the outputtext set to the uppercase value of the inputtext.

$result = @{}
$result["outputtext"] = $package.inputtext.ToUpper()
$result | ConvertTo-Json | Out-File $outputfile

You can see the full script here:

#
# Sample handler that will convert a string to uppercase
#

# Get the input and output file names from the command line
$inputfile = $args[0]
$outputfile = $args[1]

# Read the input file as a JSON document
$package = Get-Content -Raw $inputfile | ConvertFrom-Json

# Create the result and save it to the output file
$result = @{}
$result["outputtext"] = $package.inputtext.ToUpper()
$result | ConvertTo-Json | Out-File $outputfile

Input file:

{
    "inputtext": "This is my sample text"
}

Output file:

{
    "outputtext":  "THIS IS MY SAMPLE TEXT"
}

Calling the handler from Business Central

Now that the printer is defined and the handler PowerShell script is in place, it is time to call the script from Business Central.

The code below shows how a JSON document is created as the package to the handler.

We can create the package using the CreatePackage call on the print queue. The first parameter is the document name, shown in the queue. The second parameter is the name of the direct printer we created for this handler. After creating the package, a commit is needed to update the queue with the new job. Otherwise, the service that listens to the queue cannot see it.

After the commit, we can wait for the result and process it.

trigger OnAction()
var
    DirPrtQueue: Record "ForNAV DirPrt Queue";
    packageJO: JsonObject;
    resultJO: JsonObject;
    resultToken: JsonToken;
begin
    // Create the package for the local handler
    packageJO.Add('inputtext', 'This is my sample text');

    // Create a job on the queue
    DirPrtQueue.CreatePackage('Uppercase sample', 'UppercaseSample', packageJO);
    Commit(); // Commit so that the API can read the package from another session
    if DirPrtQueue.WaitForResponse(10000, resultJO) then begin
        // Read outputtext from result
        if resultJO.Get('outputtext', resultToken) then
            Message(resultToken.AsValue().AsText())
        else
            Error('The output was not found in the result.');
    end else
        Error('Request timed out');
end;