2010-01-11 220 views
36

有没有办法在.NET中将ZPL(Zebra编程语言)发送到打印机?将ZPL发送到Zebra打印机的.NET代码

我有代码来做到这一点在德尔福,但它不是很漂亮,我宁愿不尝试在.NET中重新创建它,因为它是。

+3

30k意见?人们必须像我一样,想知道ZPL是什么:)。 – kristianp 2014-07-24 07:56:55

+3

@kristianp任何曾经在零售软件上工作的人迟早会与ZPL争斗; – Vedran 2015-06-01 07:27:51

+0

零售或工业/制造印刷 – StingyJack 2017-07-07 18:25:23

回答

11

看看这个帖子:Print ZPL codes to ZEBRA printer using PrintDocument class

具体的OP挑这个功能从答案的线索:

[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

对于非Eng符号的支持,必须使用UTF16 BE编码。 – Alexufo 2014-05-13 07:13:10

+0

是否需要为此方法安装打印机驱动程序? – 2015-10-07 15:54:02

9

我管理的项目,与插座做了多年。 Zebra通常使用6101端口。我会查看代码并发布我可以做的。

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

Zebra移动打印机使用端口6101(QL,RW,MZ等)。较大的打印机通常使用端口9100. – 2010-02-08 21:22:10

+1

我在一个简单的控制台应用程序中使用此代码打印到Zebra LP 2844 Z.我不得不将端口更改为9100. – Monroecheeseman 2011-02-17 19:25:45

6

因为在C#和ZPL的搜索结果中仍然显示出高位,所以应该提到SharpZebra。这只是EPL2,但我提交了一个update,它增加了ZPL支持以及通过套接字打印,Windows打印服务和直接USB打印。

2

VB版(使用端口9100 - 使用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

我用的这两个

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

这样的组合,你将能够发送ZPL到打印机没有不管它是如何连接(LPTUSB网络共享 ...)

(上How to send raw data to a printer by using Visual C# .NET从微软的文章)创建RawPrinterHelper类:

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

调用打印方法:

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

有2个陷阱我遇到这种情况发生时,你'将带有ZPL代码的txt文件发送到打印机:

  1. 文件ha s到结束与新行字符
  2. 编码必须设置ANSI阅读txt文件时有特殊字符

    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

应该可以直接从while循环中调用SendStringToPrinter而无需将整个输入文件读取到内存中。 (如果有人用Zebra打印机可以确认它的工作原理,请编辑答案或让我知道) – Vedran 2017-06-01 08:02:53

+0

我试试这个到USB,没关系,但是当我在LPT中尝试时,它没有打印,但没有发现任何错误。任何可能的错误? – Vic 2017-06-29 09:48:01

+0

嗨,我用你的代码,但打印机不打印任何东西,打印机发送请求到后台打印,但不打印,你能帮忙吗? – Esmigol 2017-12-15 18:28:51

11

的最简单的解决方案是与将文件复制到共享打印机。
实施例C#:

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

其中:

  • inputFilePath - 路径ZPL文件(不需要特殊的扩展);
  • printerPath - 路径共享打印机,例如(!):\ 127.0.0.1 \ zebraGX
+0

这对我有效,我已经为我的标签创建了文件。 – 2014-04-29 19:14:09

+0

这在vb.net中适用于我。漂亮和简单的1班轮。我有提供给我的.zpl文件,我需要将它们发送给斑马打印机, – Zyren 2015-10-29 22:25:53

+0

这太神奇了,比其他解决方案更加整洁。它与EasyPost等已经生成ZPL文件进行打印的服务完美协作。我可以使用“\\ machine-name \\ printer-name”打印到网络上另一台计算机共享的打印机。 – blackorchid 2016-11-04 15:47:29

8

下面是使用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 
} 

来源:ZEBRA WEBSITE

相关问题