Pregunta

¿Hay una manera de enviar ZPL (Zebra Programming Language) a una impresora en .NET?

tengo el código para hacer esto en Delphi, pero no es bastante y yo prefiero no tratar de recrear en .NET como es.

¿Fue útil?

Solución

Tome un vistazo a este tema: códigos de impresión ZPL para impresora Zebra utilizando PrintDocument clase.

Específicamente, la OP recoger esta función de las respuestas a la rosca:

[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();

}

Otros consejos

De esta manera usted será capaz de enviar ZPL a una impresora sin importar cómo se conecta ( LPT , USB , Red Compartir . ..)

Crea la clase RawPrinterHelper (del artículo de Microsoft en ¿Cómo enviar datos sin procesar a una impresora utilizando Visual C # .NET ):

using System;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public class RawPrinterHelper
{
    // Structure and API declarions:
    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
    public class DOCINFOA
    {
        [MarshalAs(UnmanagedType.LPStr)] public string pDocName;
        [MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;
        [MarshalAs(UnmanagedType.LPStr)] public string pDataType;
    }
    [DllImport("winspool.Drv", EntryPoint="OpenPrinterA", SetLastError=true, CharSet=CharSet.Ansi, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
    public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);

    [DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
    public static extern bool ClosePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="StartDocPrinterA", SetLastError=true, CharSet=CharSet.Ansi, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
    public static extern bool StartDocPrinter( IntPtr hPrinter, Int32 level,  [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

    [DllImport("winspool.Drv", EntryPoint="EndDocPrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
    public static extern bool EndDocPrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="StartPagePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
    public static extern bool StartPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint="EndPagePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
    public static extern bool EndPagePrinter(IntPtr hPrinter);

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

    // SendBytesToPrinter()
    // When the function is given a printer name and an unmanaged array
    // of bytes, the function sends those bytes to the print queue.
    // Returns true on success, false on failure.
    public static bool SendBytesToPrinter( string szPrinterName, IntPtr pBytes, Int32 dwCount)
    {
        Int32    dwError = 0, dwWritten = 0;
        IntPtr    hPrinter = new IntPtr(0);
        DOCINFOA    di = new DOCINFOA();
        bool    bSuccess = false; // Assume failure unless you specifically succeed.

        di.pDocName = "My C#.NET RAW Document";
        di.pDataType = "RAW";

        // Open the printer.
        if( OpenPrinter( szPrinterName.Normalize(), out hPrinter, IntPtr.Zero ) )
        {
            // Start a document.
            if( StartDocPrinter(hPrinter, 1, di) )
            {
                // Start a page.
                if( StartPagePrinter(hPrinter) )
                {
                    // Write your bytes.
                    bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                    EndPagePrinter(hPrinter);
                }
                EndDocPrinter(hPrinter);
            }
            ClosePrinter(hPrinter);
        }
        // If you did not succeed, GetLastError may give more information
        // about why not.
        if( bSuccess == false )
        {
                dwError = Marshal.GetLastWin32Error();
        }
        return bSuccess;
    }

    public static bool SendFileToPrinter( string szPrinterName, string szFileName )
    {
        // Open the file.
        FileStream fs = new FileStream(szFileName, FileMode.Open);
        // Create a BinaryReader on the file.
        BinaryReader br = new BinaryReader(fs);
        // Dim an array of bytes big enough to hold the file's contents.
        Byte []bytes = new Byte[fs.Length];
        bool bSuccess = false;
        // Your unmanaged pointer.
        IntPtr pUnmanagedBytes = new IntPtr(0);
        int nLength;

        nLength = Convert.ToInt32(fs.Length);
        // Read the contents of the file into the array.
        bytes = br.ReadBytes( nLength );
        // Allocate some unmanaged memory for those bytes.
        pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
        // Copy the managed byte array into the unmanaged array.
        Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
        // Send the unmanaged bytes to the printer.
        bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
        // Free the unmanaged memory that you allocated earlier.
        Marshal.FreeCoTaskMem(pUnmanagedBytes);
        return bSuccess;
    }
    public static bool SendStringToPrinter( string szPrinterName, string szString )
    {
        IntPtr pBytes;
        Int32 dwCount;
        // How many characters are in the string?
        dwCount = szString.Length;
        // Assume that the printer is expecting ANSI text, and then convert
        // the string to ANSI text.
        pBytes = Marshal.StringToCoTaskMemAnsi(szString);
        // Send the converted ANSI string to the printer.
        SendBytesToPrinter(szPrinterName, pBytes, dwCount);
        Marshal.FreeCoTaskMem(pBytes);
        return true;
    }
}

Llame al método de impresión:

private void BtnPrint_Click(object sender, System.EventArgs e)
{
    string s = "^XA^LH30,30\n^FO20,10^ADN,90,50^AD^FDHello World^FS\n^XZ";

    PrintDialog pd  = new PrintDialog();
    pd.PrinterSettings = new PrinterSettings();
    if(DialogResult.OK == pd.ShowDialog(this))
    {
        RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, s);
    }
}

Hay 2 trampas que he encontrado que surgen cuando estás enviando archivos txt con los códigos de ZPL a la impresora:

  1. El archivo tiene que terminar con un carácter de nueva línea
  2. La codificación tiene que ser establecido a Encoding.Default al leer archivos TXT ANSI con caracteres especiales

    public static bool SendTextFileToPrinter(string szFileName, string printerName)
    {
        var sb = new StringBuilder();
    
        using (var sr = new StreamReader(szFileName, Encoding.Default))
        {
            while (!sr.EndOfStream)
            {
                sb.AppendLine(sr.ReadLine());
            }
        }
    
        return RawPrinterHelper.SendStringToPrinter(printerName, sb.ToString());
    }
    

He conseguido un proyecto que hace esto con tomas durante años. de Zebra normalmente utilizan el puerto 6101. Voy a mirar a través del código y publicar lo que pueda.

public void SendData(string zpl)
{
    NetworkStream ns = null;
    Socket socket = null;

    try
    {
        if (printerIP == null)
        {
            /* IP is a string property for the printer's IP address. */
            /* 6101 is the common port of all our Zebra printers. */
            printerIP = new IPEndPoint(IPAddress.Parse(IP), 6101);  
        }

        socket = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream,
            ProtocolType.Tcp);
        socket.Connect(printerIP);

        ns = new NetworkStream(socket);

        byte[] toSend = Encoding.ASCII.GetBytes(zpl);
        ns.Write(toSend, 0, toSend.Length);
    }
    finally
    {
        if (ns != null)
            ns.Close();

        if (socket != null && socket.Connected)
            socket.Close();
    }
}

La solución más sencilla es la copia de archivos a la impresora compartida.
Ejemplo en C #:

System.IO.File.Copy(inputFilePath, printerPath);

donde:

  • inputFilePath - ruta al archivo ZPL (no se requiere extensión especial);
  • printerPath - camino a la impresora compartida, por ejemplo: \ 127.0.0.1 \ zebraGX
  • (!)

Aquí es cómo hacerlo utilizando el protocolo TCP IP:

// Printer IP Address and communication port
    string ipAddress = "10.3.14.42";
   int port = 9100;

// ZPL Command(s)
   string ZPLString =
    "^XA" +
    "^FO50,50" +
    "^A0N50,50" +
    "^FDHello, World!^FS" +
    "^XZ";

   try
   {
    // Open connection
    System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient();
    client.Connect(ipAddress, port);

    // Write ZPL String to connection
    System.IO.StreamWriter writer =
    new System.IO.StreamWriter(client.GetStream());
    writer.Write(ZPLString);
    writer.Flush();

    // Close Connection
    writer.Close();
    client.Close();
}
catch (Exception ex)
{
    // Catch Exception
}

Fuente: ZEBRA WEB

Robusto ya que esto todavía está mostrando en alto en los resultados de búsqueda para C # y ZPL debería mencionar SharpZebra. Es sólo EPL2, pero he presentado una actualización que añade soporte ZPL junto con la impresión a través tomas de corriente, el servicio de cola de Windows y USB directa.

VB Version (utilizando el puerto 9100 - probado en Zebra ZM400)

Sub PrintZPL(ByVal pIP As String, ByVal psZPL As String)
    Dim lAddress As Net.IPEndPoint
    Dim lSocket As System.Net.Sockets.Socket = Nothing
    Dim lNetStream As System.Net.Sockets.NetworkStream = Nothing
    Dim lBytes As Byte()

    Try
        lAddress = New Net.IPEndPoint(Net.IPAddress.Parse(pIP), 9100)
        lSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, _                       ProtocolType.Tcp)
        lSocket.Connect(lAddress)
        lNetStream = New NetworkStream(lSocket)

        lBytes = System.Text.Encoding.ASCII.GetBytes(psZPL)
        lNetStream.Write(lBytes, 0, lBytes.Length)
    Catch ex As Exception When Not App.Debugging
        Msgbox ex.message & vbnewline & ex.tostring
    Finally
        If Not lNetStream Is Nothing Then
            lNetStream.Close()
        End If
        If Not lSocket Is Nothing Then
            lSocket.Close()
        End If
    End Try
End Sub

Yo uso la combinación de estos dos

    Private Sub sendData(ByVal zpl As String)
    Dim ns As System.Net.Sockets.NetworkStream = Nothing
    Dim socket As System.Net.Sockets.Socket = Nothing
    Dim printerIP As Net.IPEndPoint = Nothing
    Dim toSend As Byte()

    Try
        If printerIP Is Nothing Then
            'set the IP address
            printerIP = New Net.IPEndPoint(IPAddress.Parse(IP_ADDRESS), 9100)
        End If

        'Create a TCP socket
        socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        'Connect to the printer based on the IP address
        socket.Connect(printerIP)
        'create a new network stream based on the socket connection
        ns = New NetworkStream(socket)

        'convert the zpl command to a byte array
        toSend = System.Text.Encoding.ASCII.GetBytes(zpl)

        'send the zpl byte array over the networkstream to the connected printer
        ns.Write(toSend, 0, toSend.Length)

    Catch ex As Exception
        MessageBox.Show(ex.Message, "Cable Printer", MessageBoxButtons.OKCancel, MessageBoxIcon.Error)
    Finally
        'close the networkstream and then the socket
        If Not ns Is Nothing Then
            ns.Close()
        End If

        If Not socket Is Nothing Then
            socket.Close()
        End If
    End Try
End Sub


Private Function createString() As String
    Dim command As String

    command = "^XA"
    command += "^LH20,25"

    If rdoSmall.Checked = True Then
        command += "^FO1,30^A0,N,25,25^FD"
    ElseIf rdoNormal.Checked = True Then
        command += "^FO1,30^A0,N,35,35^FD"
    Else
        command += "^FO1,30^A0,N,50,50^FD"
    End If

    command += txtInput.Text
    command += "^FS"
    command += "^XZ"

    Return command

End Function

@ respuesta de liquide funciona muy bien.

System.IO.File.Copy(inputFilePath, printerPath);

Lo que me pareció de la Guía del programador de ZPL de Zebra Volumen 1 (2005) introducir descripción de la imagen aquí

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top