.Net Code to Send Zpl to Zebra Printers

.NET code to send ZPL to Zebra printers

Take a look at this thread: Print ZPL codes to ZEBRA printer using PrintDocument class.

Specifically the OP pick this function from the answers to the thread:

[DllImport("kernel32.dll", SetLastError = true)]
static extern SafeFileHandle CreateFile(string lpFileName, FileAccess dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, FileMode dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);

private void Print()
{
// Command to be sent to the printer
string command = "^XA^FO10,10,^AO,30,20^FDFDTesting^FS^FO10,30^BY3^BCN,100,Y,N,N^FDTesting^FS^XZ";

// Create a buffer with the command
Byte[] buffer = new byte[command.Length];
buffer = System.Text.Encoding.ASCII.GetBytes(command);
// Use the CreateFile external func to connect to the LPT1 port
SafeFileHandle printer = CreateFile("LPT1:", FileAccess.ReadWrite, 0, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
// Aqui verifico se a impressora é válida
if (printer.IsInvalid == true)
{
return;
}

// Open the filestream to the lpt1 port and send the command
FileStream lpt1 = new FileStream(printer, FileAccess.ReadWrite);
lpt1.Write(buffer, 0, buffer.Length);
// Close the FileStream connection
lpt1.Close();

}

Print ZPL to Zebra Printer via C#.NET

I would suggest trying the following:

  • Log into the server, preferably as the user that the service is set to run as.
  • Ensure your Zebra printer is installed as a local printer, and the printer name is correct.
  • Print a test page from the printer properties.
  • Print your ZPL manually:

net use lpt1 "printer shared name"
print "C:\Users\serviceuser\desktop\label.txt"

If you try the above and it works, I would be surprised that the code you linked does not work.

How to send a raw ZPL to zebra printer using C# via USB

EDIT: To address your update, The problem you are having is you are using SendStringToPrinter which sends a ANSI string (a null terminated) string to the printer which is not what the printer is expecting. According to the official EPL2 programming guide page 23 (Which is what you are really doing, not ZPL according to your example).

Each command line must be terminated with a Line Feed (LF) character
(Dec. 10). Most PC based systems send CR/LF when the Enter key is
pressed. The Carriage Return (CR) character is ignored by the printer
and cannot be used in place of LF.

So you must either modify SendStringToPrinter to send a \n at the end of the string instead of a \0 or you must build the ASCII byte array yourself and use RawPrinterHelper.SendBytesToPrinter yourself (like I did in my original answer below).

So to fix your simple posted example we change out your function call, we also must tell the printer to actually print by sending a P1\n

private void button2_Click(object sender, EventArgs e)
{
string s = "A50,50,0,2,1,1,N,\"9129302\"\n";
s += "P1\n";

// Allow the user to select a printer.
PrintDialog pd = new PrintDialog();
pd.PrinterSettings = new PrinterSettings();
if (DialogResult.OK == pd.ShowDialog(this))
{
var bytes = Encoding.ASCII.GetBytes(s);
// Send a printer-specific to the printer.
RawPrinterHelper.SendBytesToPrinter(pd.PrinterSettings.PrinterName, bytes, bytes.Length);
MessageBox.Show("Data sent to printer.");
}
}

//elsewhere
public static class RawPrinterHelper
{
//(Snip) The rest of the code you already have from http://support.microsoft.com/kb/322091

[DllImport("winspool.Drv", EntryPoint="WritePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, byte[] pBytes, Int32 dwCount, out Int32 dwWritten );

private static bool SendBytesToPrinter(string szPrinterName, byte[] bytes, Int32 dwCount)
{
Int32 dwError = 0, dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DOCINFOA di = new DOCINFOA();
bool bSuccess = false;

di.pDocName = "Zebra Label";
di.pDataType = "RAW";

if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
if (StartDocPrinter(hPrinter, 1, di))
{
if (StartPagePrinter(hPrinter))
{
bSuccess = WritePrinter(hPrinter, bytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
if (bSuccess == false)
{
dwError = Marshal.GetLastWin32Error();
throw new Win32Exception(dwError);
}
return bSuccess;
}
}

I did this with Zebra's older EPL2 language, but it should be very similar to what you need to do with ZPL. Perhaps it will get you started in the right direction.

public class Label
{
#region Print logic. Taken from http://support.microsoft.com/kb/322091

//Snip stuff unchanged from the KB example.

[DllImport("winspool.Drv", EntryPoint="WritePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, byte[] pBytes, Int32 dwCount, out Int32 dwWritten );

private static bool SendBytesToPrinter(string szPrinterName, byte[] Bytes, Int32 dwCount)
{
Int32 dwError = 0, dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DOCINFOA di = new DOCINFOA();
bool bSuccess = false;

di.pDocName = "Zebra Label";
di.pDataType = "RAW";

if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
if (StartDocPrinter(hPrinter, 1, di))
{
if (StartPagePrinter(hPrinter))
{
bSuccess = WritePrinter(hPrinter, Bytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
if (bSuccess == false)
{
dwError = Marshal.GetLastWin32Error();
throw new Win32Exception(dwError);
}
return bSuccess;
}
#endregion

public byte[] CreateCompleteCommand(bool headerAndFooter)
{
List<byte> byteCollection = new List<byte>();

//Static header content describing the label.
if (headerAndFooter)
{
byteCollection.AddRange(Encoding.ASCII.GetBytes("\nN\n"));
byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("S{0}\n", this.Speed)));
byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("D{0}\n", this.Density)));
byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("q{0}\n", this.LabelHeight)));
if (this.AdvancedLabelSizing)
{
byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("Q{0},{1}\n", this.LableLength, this.GapLength)));
}
}

//The content of the label.
foreach (var command in this.Commands)
{
byteCollection.AddRange(command.GenerateByteCommand());
}

//The footer content of the label.
if(headerAndFooter)
byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("P{0}\n", this.Pages)));

return byteCollection.ToArray();
}

public bool PrintLabel(string printer)
{
byte[] command = this.CreateCompleteCommand(true);
return SendBytesToPrinter(printer, command, command.Length);
}

public List<Epl2CommandBase> Commands { get; private set; }

//Snip rest of the code.
}

public abstract partial class Epl2CommandBase
{
protected Epl2CommandBase() { }

public virtual byte[] GenerateByteCommand()
{
return Encoding.ASCII.GetBytes(CommandString + '\n');
}
public abstract string CommandString { get; set; }
}

public class Text : Epl2CommandBase
{
public override string CommandString
{
get
{
string printText = TextValue;
if (Font == Fonts.Pts24)
printText = TextValue.ToUpperInvariant();
printText = printText.Replace("\\", "\\\\"); // Replace \ with \\
printText = printText.Replace("\"", "\\\""); // replace " with \"
return String.Format("A{0},{1},{2},{3},{4},{5},{6},\"{7}\"", X, Y, (byte)TextRotation, (byte)Font, HorziontalMultiplier, VertricalMultiplier, Reverse, printText);
}
set
{
GenerateCommandFromText(value);
}
}

private void GenerateCommandFromText(string command)
{
if (!command.StartsWith(GetFactoryKey()))
throw new ArgumentException("Command must begin with " + GetFactoryKey());
string[] commands = command.Substring(1).Split(',');
this.X = int.Parse(commands[0]);
this.Y = int.Parse(commands[1]);
this.TextRotation = (Rotation)byte.Parse(commands[2]);
this.Font = (Fonts)byte.Parse(commands[3]);
this.HorziontalMultiplier = int.Parse(commands[4]);
this.VertricalMultiplier = int.Parse(commands[5]);
this.ReverseImageColor = commands[6].Trim().ToUpper() == "R";
string message = String.Join(",", commands, 7, commands.Length - 7);
this.TextValue = message.Substring(1, message.Length - 2); // Remove the " at the beginning and end of the string.
}

//Snip
}

Zebra Label Printer with C#

First you need to clear up the following:

  • are you printing an RFID label or a barcode label
  • is the printer connected through USB or parallel port

For example the following snippet prints an RFID label on a Zebra printer, using the parallel port lpt1:

String strPath = "C:\\Zebra";
String zplStart = "CT~~CD,~CC^~CT~\r\n^XA\r\n^MMT\r\n^PW831\r\n^LL0599\r\n^LSO\r\n";
String zplMiddle = "^FT50,180^BY3^BCN,200,N,N,N^FD"; ///+barcode
String zplMiddle2 = "^FS\r\n^FT600,145^AAN,30,10,^FH\\^FD";///+barcode

String zplMiddle3 = "^FS^^RS8,,800,5^RFW,H^FD";//+RFID

String splend1 = "^FS\r\n^RWH,H^FS\r\n^RR10^FS\r\n^PQ1\r\n^XZ";
string filePath = strPath + "\\Books" + ".zpl";
string Prefix="..." //Define tag ID Prefix
string Sufix =".."//Define tag ID suffix
RFID ="Prefix"+ barcode +Sufix;
StreamWriter strw = new StreamWriter(filePath);
strw.Write(zplStart + zplMiddle + barcode + zplMiddle2 + barcode+ zplMiddle3 + RFID+ splend1); // assemble the three parts of the ZPL code

string command = "copy " + filePath + " lpt1"; //prepare a string with the command to be sent to the printer
// The /c tells cmd that we want it to execute the command that follows, and then exit.
System.Diagnostics.ProcessStartInfo sinf = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);

sinf.UseShellExecute = false;
sinf.CreateNoWindow = true;

System.Diagnostics.Process p = new System.Diagnostics.Process(); // new process
p.StartInfo = sinf;//load start info into process.
p.Start(); //start process (send file to printer)

The above is a sample for RFID label in your case the zpl string to feed I guess is:

string zpl="^XA^\r\nFO3,3^AD^FDZEBRA^FS\r\n^XZ";

notice I am using \r\n so as to move to next line..



Related Topics



Leave a reply



Submit