Erik's ToolBox Documentation
Index

Console

The console is the output pane of the ToolBox editor where you see the results of your script execution. It displays message() output, error messages, and timing information, for programs you run yourself and for programs the ToolBox Agent runs. This page covers how the console works, how to format output effectively, and how to manage results.


The Output Pane

The output pane is rendered using the same SourceEditor custom control as the code editor, but it is configured differently. On the "Erik's ToolBox" page, the output control is named ResultEditor and is positioned alongside the code editor in the page layout.

When the ToolBox page opens, the ResultEditor initializes as a read-only text display (Init(false) followed by SetReadOnly()). The output pane shows plain text output from your script execution.

The AI agent is not part of the console. It lives in the ToolBox Agent FactBox next to the editor when a provider is configured; see Coding Agent.


Console Capture

The console capture mechanism is the core feature that makes the output pane useful. When you run a script, the Interpreter intercepts all calls to message() and redirects them to an internal text buffer (a TextBuilder variable named Console) instead of displaying standard Business Central message dialogs.

Console capture is controlled by the Show output in console toggle on the ToolBox page. This toggle defaults to enabled when you open the page. When console capture is active:

  1. Before execution begins, the Interpreter calls CaptureConsole(true, false) to enable capture mode and clear any previous console content.
  2. A timestamp header is written: -- Started [datetime].
  3. During execution, every message() call in your script appends its text to the console buffer instead of displaying a dialog.
  4. After execution completes, the console buffer is retrieved via GetConsole(true), which appends a footer: -- Ended [datetime] - Elapsed [duration].
  5. The complete console text is loaded into the ResultEditor control for display.

If console capture is disabled, message() calls display as standard Business Central modal dialogs, and you must click OK on each one before execution continues. For scripts that produce many messages, this quickly becomes impractical, which is why console capture is enabled by default.


How message() Displays in the Console

The message() function in ToolBox scripts works the same way as in standard AL -- it accepts a format string and substitution parameters. When console capture is active, the formatted message text is written as a line in the console buffer.

Basic Messages

begin
    message('Hello, World!');
end;

Console output:

-- Started 02/07/2026 10:30:15 AM
Hello, World!
-- Ended 02/07/2026 10:30:15 AM - Elapsed 0:00:00.012

Formatted Messages with Parameters

The message() function supports %1, %2, etc., placeholders for parameter substitution:

var
    Cust : Record Customer;
begin
    if Cust.FindFirst() then
        message('Customer %1: %2 (Balance: %3)', Cust."No.", Cust.Name, Cust.Balance);
end;

Console output:

-- Started 02/07/2026 10:31:00 AM
Customer 10000: Adatum Corporation (Balance: 5,247.50)
-- Ended 02/07/2026 10:31:00 AM - Elapsed 0:00:00.045

Multiple Messages in a Loop

var
    Item : Record Item;
    i : Integer;
begin
    Item.SetRange(Type, Item.Type::Inventory);
    if Item.FindSet() then
        repeat
            i += 1;
            message('%1. %2 - %3', i, Item."No.", Item.Description);
        until (Item.Next() = 0) or (i >= 5);
    message('Displayed %1 items.', i);
end;

Console output:

-- Started 02/07/2026 10:32:00 AM
1. 1000 - Bicycle - 15 Speed
2. 1001 - Touring Bicycle
3. 1002 - Mountain Bicycle
4. 1003 - Racing Bicycle
5. 1004 - Fender Set
Displayed 5 items.
-- Ended 02/07/2026 10:32:00 AM - Elapsed 0:00:00.128

The Console and the ToolBox Agent

When the ToolBox Agent is active, the console and the agent work together:

  • Agent runs show in the console. When the agent runs the program in the editor (or a throwaway snippet) with its run_program tool, the captured console output and any diagnostics are loaded into the console within about two seconds, exactly as after a manual Run. The Show output in console toggle does not affect agent runs; their output is always captured.
  • The agent reads your runs. Every run, whether you pressed Run or the agent ran the program, is recorded as the "last run" together with its console output or diagnostics (truncated at 6,000 characters for the agent). When you ask "why did that fail?", the agent reads the last run through its get_program tool. You do not need to copy the console into the chat.
  • The chat is separate. Your conversation with the agent happens in the ToolBox Agent FactBox, not in the console. Use New Conversation in the FactBox to start over.

See Coding Agent and Tool Reference.


Viewing Formatted Output

The console displays output as plain text. Each message() call produces one line of output. You can create structured, readable output by formatting your messages carefully.

Column-Aligned Output

Use PadStr or format() with length parameters to create column-aligned output:

var
    Cust : Record Customer;
begin
    message('%-20 %-30 %1', 'No.', 'Name', 'Balance');
    message('%-20 %-30 %1', '---', '---', '-------');
    Cust.SetRange("Country/Region Code", 'US');
    if Cust.FindSet() then
        repeat
            Cust.CalcFields(Balance);
            message('%1  %2  %3', Cust."No.", Cust.Name, Cust.Balance);
        until Cust.Next() = 0;
end;

Summary Output

For data analysis scripts, include a summary section at the end:

var
    Cust : Record Customer;
    TotalBalance : Decimal;
    Count : Integer;
begin
    if Cust.FindSet() then
        repeat
            Cust.CalcFields(Balance);
            TotalBalance += Cust.Balance;
            Count += 1;
        until Cust.Next() = 0;
    message('--- Summary ---');
    message('Total customers: %1', Count);
    message('Total balance: %1', TotalBalance);
    message('Average balance: %1', TotalBalance / Count);
end;

Working with Large Result Sets

When your script outputs a large number of lines, the console pane may become difficult to navigate. Consider these strategies:

  • Limit output with counters. Add a counter variable and stop outputting after a certain number of lines:
  if i > 100 then
      message('... and %1 more records', Cust.Count() - 100);
  • Use Excel instead. For large data sets, write results to the Excel sheet using exset() instead of message(). This lets you work with the data in a spreadsheet format without overwhelming the console.
  • Output summaries only. Instead of printing every record, accumulate totals, counts, and statistics, then output a summary at the end.
  • Use filters. Narrow your record set with SetRange() and SetFilter() before iterating, so you only process and display the records you actually need.

Downloading Results

You can download the entire console output as a text file for archiving, sharing, or further processing. To download results:

  1. Run your script so that output appears in the console.
  2. Click the Download Result Text action in the toolbar.
  3. Your browser prompts you to save a file named result.txt.
  4. The file contains all text from the output pane, excluding the final line.

The download feature uses the ResultEditor's RequestSave() method, which retrieves the current text content from the control, creates an in-stream from it, and triggers a DownloadFromStream operation. The file is saved in UTF-8 encoding.

This is useful when you need to share diagnostic output with colleagues, archive the results of a data analysis script, or import the text into another tool.


Console Output in Job Queue Execution

When a ToolBox program runs through the Business Central Job Queue, console capture is also enabled. The Job Queue executor:

  1. Loads the program's source code from the Program table.
  2. Parses and compiles the code using Compiler.Parse().
  3. Enables console capture via Interpreter.CaptureConsole(true, false).
  4. Executes the AST via Interpreter.RunUnit().
  5. Checks for errors and reports them through the Job Queue's standard error handling.

In Job Queue execution, the console output is not displayed in a browser pane (since there is no user interface). Instead, the console buffer is used internally for diagnostics. If the script fails, the error message from the Interpreter's diagnostics is raised as a standard error, which the Job Queue records in its log entries.

When writing scripts intended for Job Queue execution, keep in mind that message() calls are captured but not visible to anyone unless you explicitly write the output to a table, a file, or another persistent store.


Tips for Formatting Console Output

Use Headers and Separators

Add visual structure to your output with separator lines and headers:

begin
    message('=== Customer Balance Report ===');
    message('');
    // ... data output ...
    message('');
    message('=== End of Report ===');
end;

Include Record Counts

When iterating through records, include the total count so the reader knows the scope:

var
    Cust : Record Customer;
begin
    message('Processing %1 customers...', Cust.Count());
    // ... processing logic ...
end;

Format Numbers and Dates

Use the format() function to control how values appear in the console:

begin
    message('Amount: %1', format(12345.678, 0, '<Precision,2:2><Standard Format,0>'));
    message('Date: %1', format(today, 0, '<Month,2>/<Day,2>/<Year4>'));
end;

Show Progress for Long Operations

For scripts that process many records, output progress indicators:

var
    Cust : Record Customer;
    i : Integer;
    Total : Integer;
begin
    Total := Cust.Count();
    if Cust.FindSet() then
        repeat
            i += 1;
            // ... processing ...
            if (i mod 100) = 0 then
                message('Processed %1 of %2 records...', i, Total);
        until Cust.Next() = 0;
    message('Done. Processed %1 records.', i);
end;

Use Indentation for Hierarchical Data

Indent nested data with spaces to show relationships:

var
    SalesHeader : Record "Sales Header";
    SalesLine : Record "Sales Line";
begin
    SalesHeader.SetRange("Document Type", SalesHeader."Document Type"::Order);
    if SalesHeader.FindSet() then
        repeat
            message('Order %1 - %2', SalesHeader."No.", SalesHeader."Sell-to Customer Name");
            SalesLine.SetRange("Document Type", SalesHeader."Document Type");
            SalesLine.SetRange("Document No.", SalesHeader."No.");
            if SalesLine.FindSet() then
                repeat
                    message('   Line %1: %2 x %3', SalesLine."Line No.", SalesLine.Quantity, SalesLine.Description);
                until SalesLine.Next() = 0;
        until SalesHeader.Next() = 0;
end;

Error Display in the Console

When your script encounters an error (either compilation or runtime), the console displays the error information instead of the normal script output.

Compilation Errors

Compilation errors appear as diagnostic messages with the format:

[Type] [Details] at line [LineNumber]

Multiple compilation errors are listed one per line. For example:

Unexpected Got Semicolon, was expecting Identifier at line 5
UnknownVariable x at line 8

Runtime Errors

Runtime errors display the Business Central error message. If console capture was active before the error, the output includes any message() output produced before the error occurred, followed by the error information.

Errors and the ToolBox Agent

Compile and runtime diagnostics of the last run are recorded for the agent together with the console output. Nothing is sent to the AI provider automatically; ask the agent ("Why did the last run fail?") and it reads the diagnostics with its get_program tool and proposes a fix.