2010-01-11 61 views
36

C'è un modo per inviare ZPL (Zebra Programming Language) a una stampante in .NET?Codice .NET per inviare stampanti Zebra a Zebra

Ho il codice per farlo in Delphi, ma non è bello e preferirei non provare a ricrearlo in .NET così com'è.

+3

30k visualizzazioni? Le persone devono essere come me e si chiedevano cosa fosse ZPL :). – kristianp

+3

@kristianp Chiunque abbia mai lavorato al software di vendita prima o poi finisce in una battaglia con ZPL;) – Vedran

+0

Stampa commerciale o industriale/manifatturiera – StingyJack

risposta

11

Dai un'occhiata a questa discussione: Print ZPL codes to ZEBRA printer using PrintDocument class.

In particolare l'OP raccogliere questa funzione dalle risposte al 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(); 

} 
+1

Per i simboli di supporto non Eng 'comando' deve essere codificato in UTF16 BE. – Alexufo

+0

È necessario installare il driver di stampa per questo metodo? –

9

ho gestito un progetto che fa questo con prese per anni. In genere, Zebra utilizza la porta 6101. Guarderò il codice e pubblicherò quello che posso.

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(); 
    } 
} 
+4

Le stampanti Zebra Mobile utilizzano la porta 6101 (QL, RW, MZ, ecc.). Le stampanti più grandi di solito usano la porta 9100. –

+1

Ho usato questo codice in una semplice console per stampare su Zebra LP 2844 Z. Ho dovuto cambiare la porta su 9100. – Monroecheeseman

6

Dato che questo risulta ancora alto nei risultati di ricerca per C# e ZPL, devo menzionare SharpZebra. È solo EPL2, ma ho inviato un update che aggiunge il supporto ZPL insieme alla stampa tramite socket, Windows Spool Service e diretta USB.

2

VB Version (tramite la porta 9100 - testato su 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 
0

io uso la combinazione di questi due

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 
32

In questo modo si sarà in grado di inviare ZPL a una stampante senza importa quanto esso è collegato (LPT, USB, condivisione di rete ...)

creare la classe RawPrinterHelper (dall'articolo di Microsoft sul How to send raw data to a printer by using Visual C# .NET):

using System; 
using System.Drawing; 
using System.Drawing.Printing; 
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; 
    } 
} 

chiamata la tecnica di stampa:

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); 
    } 
} 

Ci sono 2 trucchi che ho incontrato che accada quando si inviamo file txt con codici ZPL alla stampante:

  1. Il file ha s per terminare con un carattere di nuova riga
  2. codifica deve essere impostato a Encoding.Default durante la lettura di file txt ANSI con caratteri speciali

    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()); 
    } 
    
+0

Dovrebbe essere possibile chiamare SendStringToPrinter per linea direttamente dal ciclo while senza bisogno di leggere l'intero file di input in memoria. (se qualcuno con una stampante Zebra può confermare che funziona, si prega di modificare la risposta o di farmi sapere) – Vedran

+0

Ho provato questo in USB, è ok ma quando provo in LPT non ha stampato, ma non ha generato alcun errore. Qualche errore possibile? – Vic

+0

Ciao, ho usato il tuo codice ma la stampante non stampa nulla, la stampante invia la richiesta allo spool ma non stampa, puoi aiutare? – Esmigol

11

La soluzione più semplice è con la copia dei file di stampante condivisa.
Esempio in C#:

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

dove:

  • inputFilePath - percorso del file ZPL (estensione speciale non è richiesta);
  • printerPath - percorso condiviso della stampante, per esempio (!): \ 127.0.0.1 \ zebraGX
+0

Questo ha funzionato per me, stavo già creando file per le mie etichette. –

+0

Questo ha funzionato per me in vb.net. bella e semplice 1 fodera. Ho i file .zpl che mi vengono forniti e ho bisogno di inviarli a una stampante zebra, – Zyren

+0

Questo è sorprendente, molto più ordinato di altre soluzioni. Funziona perfettamente con servizi come EasyPost che già generano un file ZPL per la stampa. Sono stato in grado di stampare su una stampante condivisa da un'altra macchina sulla rete con solo "\\ nome-macchina \\ nome-stampante". – blackorchid

8

Ecco come farlo utilizzando il protocollo 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 
} 

Fonte: ZEBRA WEBSITE

Problemi correlati