13Printing
ZplPrinterClient sends raw TCP to port 9100 and queries the status via ~HS (ZplPrinterStatus: PaperOut, Paused, HeadOpen, RibbonOut, OverTemperature, UnderTemperature, LabelsRemainingInBatch, FormatsInBuffer).
var printer = new ZplPrinterClient("192.168.1.50") // Port 9100 (Raw)
{
Timeout = TimeSpan.FromSeconds(5),
};
ZplPrinterStatus status = await printer.GetStatusAsync(); // ~HS
if (!status.IsReady)
throw new InvalidOperationException(
$"Papier leer: {status.PaperOut}, Kopf offen: {status.HeadOpen}, Pause: {status.Paused}");
await printer.SendAsync(zpl);
await printer.SendAsync(label, dpi: 203, copies: 5);
Connections: IPrinterConnection
All transports implement IPrinterConnection (SendAsync(byte[]), QueryAsync); extension methods send ZPL strings and labels and query the ~HS status via GetStatusAsync(). PrinterSettings + PrinterConnectionFactory.Create make the transport configurable.
// one interface for all transports
await using IPrinterConnection printer = PrinterConnectionFactory.Create(new PrinterSettings
{
CommunicationType = CommunicationType.Network, // Network, Serial, Usb, File, WindowsDriver, Cups, Stream
Host = "192.168.1.50", Port = 9100,
Timeout = TimeSpan.FromSeconds(5),
});
ZplPrinterStatus? status = await printer.GetStatusAsync(); // ~HS (null for write-only transports)
await printer.SendAsync(zpl);
await printer.SendAsync(label, dpi: 203, copies: 2);
// generated directly
IPrinterConnection tcp = new TcpPrinterConnection("192.168.1.50");
IPrinterConnection serial = new SerialPrinterConnection("COM3", 9600, Parity.None, 8, StopBits.One, Handshake.XOnXOff);
IPrinterConnection usb = new RawFilePrinterConnection("/dev/usb/lp0"); // or \\.\USB001, file
IPrinterConnection cups = new CupsPrinterConnection("Zebra_ZD421") { JobTitle = "Versand" };
IPrinterConnection mem = new StreamPrinterConnection(new MemoryStream()); // Tests
if (OperatingSystem.IsWindows())
{
IPrinterConnection spooler = new WindowsSpoolerPrinterConnection("ZDesigner ZD421-203dpi", documentName: "Versand");
}
| Class | CommunicationType | Status (~HS) |
|---|---|---|
TcpPrinterConnection | Network (Raw, port 9100) | yes |
SerialPrinterConnection | Serial (baud, parity, handshake) | yes |
RawFilePrinterConnection | Usb, File (device path or file) | no |
WindowsSpoolerPrinterConnection | WindowsDriver (RAW print job, Windows only) | no |
CupsPrinterConnection | Cups (lp -o raw) | no |
StreamPrinterConnection | Stream (any Stream, tests) | if readable |
Virtual printer (TCP 9100)
ZplVirtualPrinter listens on the raw port, renders incoming ZPL and EPL jobs (EPL is detected) and saves every label as PNG or PDF – ideal for testing applications that would otherwise print to a Zebra. Status queries are answered as a ready printer (HostQueryHandler for custom responses). As a console program: dotnet run --project samples/VirtualPrinter -- --port 9100 --out labels [--pdf] [--any].
await using var printer = new ZplVirtualPrinter(9100, IPAddress.Loopback)
{
RenderSettings = new ZplRenderSettings { Dpi = 203, OutputFormat = ZplOutputFormat.Png },
OutputDirectory = "labels", // every label as labels/*.png
};
printer.LabelReceived += (_, e) => Console.WriteLine($"Etikett #{e.Index} → {e.FilePath}");
printer.Start(); // answers ~HS, ~HI and ~HQ (ES, SN, OD …)
Print settings, extended status, discovery & dry run
ZplJobSettings generates ^MM (tear-off, peel-off, cutter, RFID …), ^MN (gap, mark, continuous), ^MT, ^LL/^ML, ^MD, ^PR and the orientation, and inserts them after every ^XA. GetExtendedStatusAsync evaluates ~HQES (error and warning flags), plus serial number, odometer and ~HI. PrinterDiscovery.FindUsbPrintersAsync finds USB printers; with EnablePrinting = false the factory returns a DryRunPrinterConnection that only logs. Further transports: TCP, serial, USB/file, parallel port, Windows spooler, CUPS, stream.
var settings = new PrinterSettings
{
Host = "127.0.0.1", Port = 9100,
EnablePrinting = true, // false = dry run (DryRunPrinterConnection)
Job = new ZplJobSettings
{
PrintMode = PrintMode.Cutter, // ^MMC
MediaTracking = MediaTracking.Gap, // ^MNY
MediaType = MediaType.DirectThermal, // ^MTD
Darkness = 20, PrintSpeed = 4, // ^MD, ^PR
Orientation = JobOrientation.Portrait180,
},
};
await using IPrinterConnection conn = PrinterConnectionFactory.Create(settings);
await conn.SendAsync(settings.Job.Apply(zpl));
ZplExtendedStatus? status = await conn.GetExtendedStatusAsync(); // ~HQES
if (status is { IsReady: false }) Console.WriteLine(status.Errors);
IReadOnlyList<DiscoveredPrinter> usb = await PrinterDiscovery.FindUsbPrintersAsync();
More on zplCloud.com: Guide: Print control (^MD, ^PR, cut, mirror)

