Check network printer status (online/offline) in BC OnPrem

In a recent Business Central 16 OnPrem project, a colleague had the problem of having to detect whether a printer was online or offline. Based on this, he wanted to decide on which device the printout should land. After making sure that we were dealing exclusively with network printers, we decided to check whether a socket connection was established or not. If the latter is the case, the printer is not accessible.

Actually, it’s some kind of a port scanner used to check your network printer status 😛

Socket Connection

Here you find the try function that checks the socket connection using the given parameters. For sure this is a universal socket connection and you might do whatever you want with it besides our printer check.

[TryFunction]
local procedure TryCheckPrinterStatus(IP: Text; Port: Integer; ConnectTimeout: Integer; var Success: Boolean)
var
    IPAddress: DotNet IPAddress;
    TcpSocket: DotNet TcpSocket;
    IAsyncResult: DotNet IAsyncResult;
    IPEndpoint: DotNet IPEndpoint;
    Object: DotNet Object;
    AsyncCallback: DotNet AsyncCallback;
    AddressFamily: DotNet AddressFamily;
    ProtocolType: DotNet ProtocolType;
    SocketType: DotNet SocketType;
begin  
    //Check network printer status
    //Parse IP Address
    IPAddress := IPAddress.Parse(IP);

    //Create IP Endpoint using IP and Port (9100)
    IPEndpoint := IPEndpoint.IPEndPoint(IPAddress, Port);

    //Try connect to printer socket
    TcpSocket := TcpSocket.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    IAsyncResult := TcpSocket.BeginConnect(IPEndpoint, AsyncCallback, Object);

    Success := IAsyncResult.AsyncWaitHandle.WaitOne(ConnectTimeout, true);
    if Success then
        TcpSocket.EndConnect(IAsyncResult)
    else
        TcpSocket.Close();
end;

Wrapper Function

Around this TryFunction we build a wrapper function which is accessible from external code.

procedure CheckPrinterStatus(IP: Text; Port: Integer; ConnectTimeout: Integer): Boolean
var
    Success: Boolean;
begin    
    if not TryCheckPrinterStatus(IP, Port, ConnectTimeout, Success) then;
        exit(Success);
end;

DotNet Variables

To make use of DotNet, we must declare the assemblies.

Dotnet
{
    assembly(mscorlib)
    {
        type("System.Object"; "Object")
        {
        }
        type("System.AsyncCallback"; "AsyncCallback")
        {
        }
        type("System.IAsyncResult"; "IAsyncResult")
        {
        }       
    }
    assembly("System")
    {
        Version = '4.0.0.0';
        Culture = 'neutral';
        PublicKeyToken = 'b77a5c561934e089';

        type("System.Net.IPEndPoint"; "IPEndpoint")
        {
        }
        type("System.Net.Sockets.AddressFamily"; "AddressFamily")
        {
        }
        type("System.Net.Sockets.SocketType"; "SocketType")
        {
        }
        type("System.Net.Sockets.ProtocolType"; "ProtocolType")
        {
        }
        type("System.Net.Sockets.Socket"; "TcpSocket")
        {
        }
        type("System.Net.Sockets.TcpClient"; "TcpClient")
        {
        }
        type("System.Net.IPAddress"; "IPAddress")
        {
        }
    }
}

Dont’ forget to include the “Assembly Probing Path” in your settings.json.

{
    "al.assemblyProbingPaths": [
        "C:/Windows/assembly"
    ]
}

Usage

Last but not least you could use this snippet from wherever you like.

 //Check Printer
Message('%1', OnPremPrintMgt.CheckPrinterStatus('192.168.2.189', 9100, 500));

Network printer status on a page

network printer status
Printer Status Message

Actually, this post correlates pretty well with my post about “ZPL printing to socket“.
For sure it works with Dynamics NAV as well.

... is a technical consultant and developer at Comsol Unternehmenslösungen AG in Kronberg/Taunus. Major tasks are the architecture and implementation of complex, usually cross-system applications in and around Microsoft Dynamics 365 Business Central.

Leave a Reply

Your email address will not be published. Required fields are marked *