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
Actually, this post correlates pretty well with my post about “ZPL printing to socket“.
For sure it works with Dynamics NAV as well.